打字稿:具有受保护构造函数的抽象类中的instanciate子类

时间:2018-02-20 11:19:15

标签: typescript polymorphism

我有一个用于创建子类的类,其中包含可在数据库中修改的属性。 我希望child classe只包含这样的属性:

export class Tags extends AbstractTagFactory {
    public a = "ok";
    public b = "oui";
    public premier = "tata";
    public g = 4;
}

我创建了一个抽象类:

import { BaseSQL, IResult } from "@caam/basesql";
import { ITag } from "./tag.interface";

export abstract class AbstractTagFactory {

    public static async create
    <T extends AbstractTagFactory>(this: {new (): T}): Promise<T> {
        const child = new this() as T;
        return await child.buildInstance() as T;
    }

    private static changeAttribute(object: AbstractTagFactory, attributeName: string, newValue: any): void {
        object = Object.defineProperty(object, attributeName, {
            value: newValue,
            writable: true,
        });
    }

    public constructor() {
        return ;
    }

    private async buildInstance(): Promise<AbstractTagFactory> {
        const sql = new BaseSQL();
        const result = await sql.executeQuery("SELECT tag, value FROM tags ORDER BY tag ASC");
        const keys: Set<string> = new Set(this.getKeys());
        const tags: ITag[] = result.recordset;
        for (const tag of tags) {
            const key = keys.has(tag.tag);
            if (key) {
                AbstractTagFactory.changeAttribute(this, tag.tag, tag.value);
            }
        }
        return this;
    }

    private getKeys(): string[] {
        return Object.keys(this);
    }

    private getEntries(): string[][] {
        return Object.entries(this);
    }
}

这里是index.ts中的代码

async function exec() {
    const d = await Default.create<Default>();
}
exec().then(() => { process.exit(); });

这很好用,但我想把构造函数放在受保护的访问中。 但是,如果我这样做,typescript会抛出一个错误:

src/index.ts(11,21): error TS2684: The 'this' context of type 'typeof Default' is not assignable to method's 'this' of type 'new () => Default'.
  Cannot assign a 'protected' constructor type to a 'public' constructor type.

有没有办法在抽象方法中实现子类?

感谢您的帮助

1 个答案:

答案 0 :(得分:1)

谢谢@tao

使用Reflect.construct()

我刚刚编辑了这样的create方法:

public static async create
<T extends AbstractTagFactory>(): Promise<T> {
    const child = Reflect.construct(this, []) as T;
    return await child.buildInstance() as T;
}