如何将鸭子类型的联合类型处理为 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)
但是那并不太管用
我有一种感觉,这里一定有一个常见的做法。我也想知道是否有两种方法可以做到这一点,(1) 使用 ES6 类和 (2) 不使用 ES6 类。对于后者,如果我们告诉类型系统如何按鸭子类型处理 JSON,它似乎应该能提供帮助。
答案#1
你快完成了。还有几件事需要修正:
- 为了创建类型的实例,你应该使用
new关键字 -new duckTypeMap[x.type]; - 为了初始化这个实例的字段,你应该创建一个复制构造函数,或者只是映射 JSON 对象(手动或使用某个库)。参考这个答案作为示例。
- 如果你的类实现了该接口,它应该声明该接口的成员。同时,不确定使用
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;
});
在遍历“typed”数组时,要确定项目类型,你可以使用instanceof操作符:
if(item instanceof RefundedEvent)
