如何处理Duck类型的联合类型到TypeScript接口?

时间:2016-07-13 20:54:02

标签: typescript

我是TypeScript的新手,仍然试图掌握一切。

我有一系列形成时间轴的事件。他们看起来像这样:

const timeline = [{
  type: 'payment',
  amount: '12.23 USD',
  when: '<iso timestamp>'
},{
  type: 'payment',
  amount: '12.23 USD',
  when: '<iso timestamp>'
},{
  type: 'refunded',
  amount: '2.00 USD',
  when: '<iso timestamp>'
},{
  type: 'payment',
  amount: '12.23 USD',
  when: '<iso timestamp>'
},{
  type: 'delinquent',
  when: '<iso timestamp>'
}]

所以我已经离开并将IEvent定义为联合类型:

interface IPaymentEvent {
  amount: string,
  when: string
}

interface IRefundedEvent {
  amount: string,
  when: string
}

interface IDelinquentEvent {
  when: string
}

type IEvent = IPaymentEvent | IRefundedEvent | IDelinquentEvent

问题是我很困惑如何在我的代码中使用这种类型的信息。如何将该时间轴转换为我刚定义的实际类型?当我遍历数组时,如何解构联合类型?

我的尝试看起来像这样:

class PaymentEvent implements IPaymentEvent {}
class RefundedEvent implements IRefundedEvent {}
class DelinquentEvent implements IDelinquentEvent {}

const duckTypeMap = {
  payment: PaymentEvent,
  refunded: RefundedEvent,
  delinquent: DelinquentEvent
}

const typedTimeline = timeline.map(x => {
  return duckTypeMap[x.type](x)
})

console.log(typedTimeline)

But that's not quite working

我觉得这里必须有一个共同的做法。我也有兴趣,如果有两种方法可以做到这一点,(1)使用es6类,(2)没有es6类。对于后者,似乎类型系统应该能够帮助我们告诉它如何鸭子类型JSON。

1 个答案:

答案 0 :(得分:3)

你几乎就在那里。几件事情无法解决:

  1. 要创建类型实例,您应使用new关键字 - new duckTypeMap[x.type];
  2. 为了初始化这个实例的字段,您应该创建复制构造函数或者只是映射json对象(手动或使用某些库)。例如,请查看this答案。
  3. 如果您的类实现了接口,则应声明此接口的成员。还不确定使用union类型可以获得什么。为了拥有多态数组,您只需定义具有IEvent属性的单个接口when,并在所有类中实现它。
  4. 这样的事情:

    interface IEvent {
        when: string
    }
    
    class PaymentEvent implements IEvent {
        public amount:string;
        public when:string;
    }
    
    const typedTimeline:IEvent[] = timeline.map(x => {
        let target = new duckTypeMap[x.type];
        for (const key in x) {
            target[key] = x[key];
        }
        return target;
    });
    

    在迭代&#34;键入&#34;时确定项目类型数组,您可以使用instanceof运算符:

    if(item instanceof RefundedEvent)