首页 > 解决方案 > 子类构造函数的泛型

问题描述

我正在寻找一种以[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 A另外,new () => A和有什么区别{new (): A}

标签: typescriptgenericsinheritance

解决方案


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

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

游乐场链接


推荐阅读