在 TypeScript 中使用类型变量从抽象 class 为派生的 classes 分配泛型
Assigning a generic type for derived classes from an abstract class with type variables in TypeScript
我有一个抽象 class Base
接受要在 class 中使用的类型变量 <T>
。然后我有很多派生的 classes 明确定义了类型,比如 class Derived extends Base<string> {...}
我想要一个变量(或变量数组),其类型可以是任何派生的 classes,无论 <T>
是什么。然后我希望能够使用该变量来创建这些 Derived classes.
的新实例
这是我尝试过的一些代码。从那里,我迷路了。
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"
您需要为构造函数定义类型:
type CtorBase = new () => Base<any>;
现在您可以使用它来保存 Base 的构造函数列表:
let classes_C: CtorBase [] = [];
classes_C.push(Derived);
我的建议是:
let classes: Array<new (...args: any) => Base<any>> = [];
classes.push(Derived); // okay
classes.push(SecondDerived); // okay
数组的元素类型应该是"a constructor of any subtype of Base<T>
for any T
"。要说 "a constructor of X
" 作为类型,您可以使用 any
或 any[]
类型的 new
able signature, like new () => X
. Note that the signature specifies what types and number arguments the constructor expects; if you don't care, then you can use a rest argument,例如 new (...args: any) => X
.
由于您正在构建的类型是任何 T
的 Base<T>
的任何子类型,并且您可能不需要跟踪哪个,那么 Base<any>
可能是好的足够。 (如果不是,那么请详细说明它不起作用的用例)。
好的,希望对您有所帮助;祝你好运!
我有一个抽象 class Base
接受要在 class 中使用的类型变量 <T>
。然后我有很多派生的 classes 明确定义了类型,比如 class Derived extends Base<string> {...}
我想要一个变量(或变量数组),其类型可以是任何派生的 classes,无论 <T>
是什么。然后我希望能够使用该变量来创建这些 Derived classes.
这是我尝试过的一些代码。从那里,我迷路了。
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"
您需要为构造函数定义类型:
type CtorBase = new () => Base<any>;
现在您可以使用它来保存 Base 的构造函数列表:
let classes_C: CtorBase [] = [];
classes_C.push(Derived);
我的建议是:
let classes: Array<new (...args: any) => Base<any>> = [];
classes.push(Derived); // okay
classes.push(SecondDerived); // okay
数组的元素类型应该是"a constructor of any subtype of Base<T>
for any T
"。要说 "a constructor of X
" 作为类型,您可以使用 any
或 any[]
类型的 new
able signature, like new () => X
. Note that the signature specifies what types and number arguments the constructor expects; if you don't care, then you can use a rest argument,例如 new (...args: any) => X
.
由于您正在构建的类型是任何 T
的 Base<T>
的任何子类型,并且您可能不需要跟踪哪个,那么 Base<any>
可能是好的足够。 (如果不是,那么请详细说明它不起作用的用例)。
好的,希望对您有所帮助;祝你好运!