繁体   English   中英

在typescript中的基类构造函数参数中引用子类的实例类型

[英]Referencing an instance type of a child class in base class constructor parameter in typescript

我正在使用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',
});

在构造函数中没有内置的方法来访问派生类。 多态this在构造函数中是不可访问的,正如评论中指出的那样。

最简单的选择是向AbstractEvent添加一个类型参数。 type参数将是派生类中的类本身。 这样做的优点是不需要任何额外运行时代码的解决方案。 不需要派生类型构造函数。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM