我正在寻找一种以通用方式从以下代码中表达[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}
有什么区别?
答案 0 :(得分:1)
最简单的答案是typeof A
,new () => A
和{new (): A}
之间的区别是什么。最后两个是等效的,{ new() : A }
语法是new () => A
的更详细的表亲。使用更详细的版本的原因是因为它允许您为构造函数指定更多重载,并且还允许您指定额外的成员(即静态方法)。 typeof A
是类A
,其中包含构造函数签名以及任何静态变量。如果您只关心能够创建类的实例,那么简单的构造函数签名就足够了。如果还需要访问静态变量,则需要typeof Class
。
对于您的其他问题,问题在于打字稿将抽象类的构造函数视为第二类构造函数的一部分。除了在派生类内部之外,它不是构造函数,由于不应实例化该类,因此这不是一个坏主意。但是,在这种情况下,这意味着在static
上调用A
时,类A
将无法满足其具有可调用构造函数(this: 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))