我正在研究Typescript 3.4.2和Node v.12中的事件源原型。
效果很好,但是我想避免为每种事件编写复制粘贴的构造函数和AbstractEvent<T>
之类的泛型。
是否有一种方法可以基于子类实例在父类构造函数中启用TS类型检查?
abstract class AbstractEvent {
// I want type system work here something like:
// public constructor(data: InstanceType< typeof this >)
public constructor(data: any) {
for (const key in data) {
this[key] = data[key];
}
}
}
class PackCreatedEvent extends AbstractEvent {
public readonly id: string;
public readonly title: string;
// I want to avoid writing constructors for each event type
// and also trying to avoid extra interfaces
public constructor(data: PackCreatedEvent) {
super(data);
}
}
class UserCreatedEvent extends AbstractEvent {
public readonly id: string;
public readonly email: string;
}
// instantiating
const packCreatedEvent1 = new PackCreatedEvent({
id: 'GSNV-FGHT-FGHF-HFTH',
title: 'Apple',
});
const packCreatedEvent2 = new PackCreatedEvent({
id: 'ABGF-FGHT-FGHF-HFTH',
title: 'Banana',
// uncomment to see error
// someBadProperty: 'test',
});
const userCreatedEvent = new UserCreatedEvent({
id: 'GSNV-FGHT-FGHF-HFTH',
email: 'test@mail.com',
// not a valid property
// and not error because of 'any' in AbstractEvent.constructor
someBadProperty: 'test',
});
答案 0 :(得分:2)
在构造函数中没有内置的方法可以访问派生类。正如注释中指出的,多态this
在构造函数中不可访问。
最简单的选择是将类型参数添加到AbstractEvent
。类型参数将是派生类中的类本身。这样做的好处是不需要任何额外的运行时代码的解决方案。不需要派生类型构造函数。
abstract class AbstractEvent<T extends AbstractEvent<any>> {
public constructor(data: T) {
for (const key in data) {
this[key as any] = data[key];
}
}
}
class PackCreatedEvent extends AbstractEvent<PackCreatedEvent> {
public readonly id: string;
public readonly title: string;
}
class UserCreatedEvent extends AbstractEvent<UserCreatedEvent> {
public readonly id: string;
public readonly email: string;
}
const userCreatedEvent = new UserCreatedEvent({
id: 'GSNV-FGHT-FGHF-HFTH',
email: 'test@mail.com',
// not a valid property
// error now
someBadProperty: 'test',
});