1

我有一个抽象类Base,它接受<T>要在类中使用的类型变量。然后我有很多明确定义类型的派生类,比如class Derived extends Base<string> {...}

我想要一个变量(或变量数组),其类型可以是任何派生类,不管是什么<T>。然后我希望能够使用该变量来创建这些派生类的新实例。

这是我尝试过的一些代码。从那里,我迷路了。

TypeScript Playground 链接

abstract class Base<T> {
    abstract value: T;
}

class Derived extends Base<string> {
    value = 'Hello world!';
}

class SecondDerived extends Base<number> {
    value = 1234;
}

// This has type (typeof Derived | typeof SecondDerived)
let classes_A = [Derived, SecondDerived];

// This obviously works too, but with many derived classes can get long and tedious
let classes_B: (typeof Derived | typeof SecondDerived)[] = [];
classes_B.push(Derived);
classes_B.push(SecondDerived);

// This does NOT work
let classes_C: Base<any>[] = [];
classes_C.push(Derived); // "typeof Derived is not assignable to type Base<any>"

// This does NOT work
let classes_D: Base<unknown>[] = [];
classes_D.push(Derived); // "typeof Derived is not assignable to type Base<unknown>"

// This does NOT work
let classes_E: Base<string>[] = [];
classes_E.push(Derived); // "typeof Derived is not assignable to type Base<string>"

// This does NOT work
let classes_F: (typeof Base)[] = [];
classes_F.push(Derived); // "typeof Derived is not assignable to typeof Base"
4

2 回答 2

1

我的建议是这样的:

let classes: Array<new (...args: any) => Base<any>> = [];
classes.push(Derived); // okay
classes.push(SecondDerived); // okay

数组的元素类型应该是“任意子类型的构造函数Base<T>T。要说“的构造函数X”作为一种类型,你可以使用一个有new能力的签名,比如new () => X. 请注意,签名指定构造函数期望的类型和数量参数;如果您不在乎,那么您可以使用类型或的rest 参数,例如.anyany[]new (...args: any) => X

由于您正在构建的类型是 any 的任何子类型,Base<T>并且T您可能不需要跟踪哪个,那么Base<any>可能就足够了。(如果不是,那么请详细说明这不起作用的用例)。

好的,希望有帮助;祝你好运!

Playground 代码链接

于 2020-02-06T20:38:21.830 回答
1

您需要为构造函数定义类型:

type CtorBase = new () => Base<any>;

现在您可以使用它来保存 Base 的构造函数列表:

let classes_C: CtorBase [] = [];
classes_C.push(Derived);
于 2020-02-06T20:29:52.127 回答