【问题标题】:generic type of child class constructor子类构造函数的泛型
【发布时间】:2019-02-20 14:05:16
【问题描述】:

我正在寻找一种方法来以通用方式从以下代码中表达[B, C] 的类型。如果我像现在一样悬停types,我会得到const types: (typeof B | typeof C)[],这有点冗长,并且随着新项目的添加可能会变得很长。

abstract class A {
    static staticF<T extends A>(this: new () => T): string {
        return 'A'
    }
}

class B extends A {
    static bProp = 1
}
class C extends A {
    static cProp = 1
    static staticF<T extends A>(this: new () => T): string {
        return 'B'
    }
}

const types = [B, C]
types
    .map(t => t.staticF())
    .forEach(x => console.log(x))

我尝试使用const types: typeof A[],但出现以下错误:

“typeof A”类型的“this”上下文不能分配给“new () => A”类型的方法“this”。 无法将抽象构造函数类型分配给非抽象构造函数类型。

我也试过const types: typeof extends A[],但 TS 认为我喝醉了。

如何从共享同一个父类的类中表达多个类构造函数的类型?

另外,typeof Anew () =&gt; A{new (): A} 有什么区别?

【问题讨论】:

    标签: typescript generics inheritance


    【解决方案1】:

    回答最简单的部分是typeof Anew () =&gt; A{new (): A} 之间的区别。最后两个是等价的,{ new() : A } 语法是new () =&gt; A 的更详细的表亲。使用前一个更详细版本的原因是因为它允许您为构造函数指定更多重载,并且还允许您指定额外的成员(即静态方法)。 typeof A 是类 A,它包括构造函数签名以及任何静态信息。如果您只关心能够创建类的实例,那么简单的构造函数签名就足够了。如果您还需要访问静态数据,则需要typeof Class

    至于您的其他问题,问题在于打字稿将抽象类的构造函数视为第二类构造函数。它不是构造函数,除非在派生类内部,因为不应实例化该类,所以这不是一个坏主意。然而,在这种情况下,这意味着当在 A 上调用 static 时,A 类将不满足它具有可调用构造函数的约束 (this: new () =&gt; T)

    我发现最简单的解决方案是创建一个扩展typeof A 的接口。这实际上将消除构造函数的抽象性并允许您创建所需的数组:

    type AClass = (typeof A);
    interface DerivedAClass extends AClass {}
    
    let types : DerivedAClass[] = [B, C];
    types
        .map(t => t.staticF()) // T of staticF will be DerivedAClass
        .forEach(x => console.log(x))
    

    Playground link

    【讨论】:

    • 这就像一个魅力,你的解释让我很清楚。非常感谢!
    猜你喜欢
    • 2018-12-22
    • 2010-10-16
    • 2017-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多