如何将duck类型的联合类型处理为TypeScript接口?

如何将duck类型的联合类型处理为TypeScript接口?,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

我对打字还不熟悉,但仍在努力掌握诀窍

我有一系列的事件组成了一个时间轴。它们看起来像这样:

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>'
}]
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)
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;
});
问题是我不知道如何在代码中使用这种类型信息。如何将时间线转换为我刚才定义的实际类型?当我迭代数组时,如何解构联合类型

我的尝试是这样的:

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>'
}]
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)
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;
});


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

您就快到了。有几件事需要解决:

  • 为了创建类型的实例,您应该使用
    new
    关键字-
    newducktypemap[x.type]
  • 为了初始化该实例的字段,您应该创建复制构造函数或只映射json对象(手动或使用某些库)。例如,看一看答案
  • 如果您的类实现了该接口,它应该声明该接口的成员。也不确定使用
    union
    type可以获得什么好处。为了拥有多态数组,您可以使用
    when
    属性定义单个接口
    IEvent
    ,并在所有类中实现它
  • 大概是这样的:

    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>'
    }]
    
    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)
    
    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;
    });
    
    要在迭代“类型化”数组时确定项目类型,可以使用
    instanceof
    运算符:

    if(item instanceof RefundedEvent)
    

    考虑使用字符串作为类型,如<代码>接口IrFunDeDebug {类型:“退还”;}(2)BuMeM-有没有方法自动生成表示这种类型的类?(3) 联合类型的意义在于,事件可能具有完全不同的字段。我希望能够迭代,检查实例,并以不同的方式呈现事件。等等,我可以这样做吗<代码>类型paymentEvent={when:string,type:string,amount:string}
    根据什么自动生成?Json?(3) -如果不使用任何通用对象,则可以使用
    任意
    对象的数组。是的,据我所知,您可以定义内联类型