【问题标题】:Typescript, how to use a constructor of a class extending an abstract class as parameterTypescript,如何使用扩展抽象类的类的构造函数作为参数
【发布时间】:2021-04-19 17:47:16
【问题描述】:

我有一个抽象类A。然后我有两个类,BC,它们扩展了这个抽象类。

(示例代码):

abstract class A {
    private name: string;

    abstract saluto(): void;

    constructor(name: string) {
        this.name = name;
    }
}

class B {
    saluto(): void {
        console.log(`Hello ${this.name}`);
    }

    constructor(name: string) {
        super(name);
    }
}

class C {
    saluto(): void {
        console.log(`Ciao ${this.name}`);
    }

    constructor(name: string) {
        super(name);
    }
}

我有一个函数,它给定数组const generators = [B, C],一个参数返回BC 创建的实例,并将参数传递给constctor。

例如:

const generators = [B, C];

function generate(generators: typeof A[], name: string): A[] {
    return generators.map(gen => new gen(name)); // Here I have the error
}
const instances = generate(generators, 'Eugenio');

这里我有一个错误,因为它说Cannot create an instance of an abstract class.

我该如何解决这个问题?应该有办法告诉 tsc 生成器不是 A 本身,而是扩展它的非抽象类。

【问题讨论】:

    标签: typescript


    【解决方案1】:

    当你使用typeof A 时,你基本上创建了一个类似于abstract new(name: string) => A 的类型。构造函数 (TS 4.2 abstract constructor signature) 上的 abstract 关键字将此类/构造函数标记为不可实例化。所以,如果你想要一个可实例化的类,你需要在没有abstract newnew (playground) 的情况下键入它:

    function generate(generators: (new(name: string) => A)[], name: string): A[] {
        return generators.map(gen => new gen(name)); // No error anymore
    }
    

    编辑:自动推断构造函数签名。

    为此,您通常会使用ConstructorParameters,但这是不可能的,因为typeof A 返回一个抽象构造函数,而 ConstructorParameters 仅适用于普通构造函数。因此,我们必须使用infer (playground) 自己键入该实用程序类型:

    type AbstractConstructorParameters<T> = T extends abstract new(...args: infer P) => any ? P : never;
    
    type ParametersOfA = AbstractConstructorParameters<typeof A>;
    
    function generate(generators: (new(...args: ParametersOfA) => A)[], ...args: ParametersOfA): A[] {
        return generators.map(gen => new gen(...args)); // No error anymore
    }
    

    【讨论】:

    • 谢谢,它成功了。但是它不会自动获得A 的构造函数的签名。我的意思是,因为A的构造函数有签名(string) =&gt; A,有没有更简洁的方法让我避免在new之后写签名?
    • 我已经更新了这个问题,以推断构造函数签名。
    猜你喜欢
    • 2018-09-26
    • 1970-01-01
    • 2015-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多