【问题标题】:How to handle duck-typed union types to TypeScript interfaces?如何将鸭子类型的联合类型处理为 TypeScript 接口?
【发布时间】:2016-07-14 13:46:25
【问题描述】:

我是 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 进行鸭式输入,类型系统似乎应该能够提供帮助。

【问题讨论】:

  • 考虑使用字符串作为类型,如interface IRefundedEvent { type: "refunded"; }

标签: typescript


【解决方案1】:

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

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

类似这样的:

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)

【讨论】:

  • (2) 太糟糕了——有没有办法自动生成一个代表这种类型的类? (3)联合类型的重点是因为事件可能具有完全不同的字段。而且我希望能够迭代、检查实例并以不同的方式呈现事件。
  • 等等,我可以这样做吗? type paymentEvent = {when: string, type: string, amount: string}
  • 从什么自动生成?杰森? (3) - 如果你没有对它们做任何共同的事情,可以使用 any 对象的数组。是的,据我所知,您可以定义内联类型
猜你喜欢
  • 1970-01-01
  • 2020-04-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-26
  • 2018-07-27
相关资源
最近更新 更多