javascript - 在 TypeScript 中返回泛型类型的构造函数
我在努力定义如何编写 TypeScript 代码来表示函数返回泛型类型的构造函数。关于如何传递泛型类型的构造函数有很多示例,但关于如何返回却没有。
请检查以下示例:
这是抽象类的一部分:
getModel(): (new () => T) {
throw new Error('Method not implemented.'); // Error because don't know how to fix it
}
当我在派生类中尝试这样实现它时:
getModel(): typeof User {
return User;
}
我遇到了以下错误:
Type '() => typeof User' is not assignable to type '() => new () => User'.
如果我知道如何在抽象类中指定,我可以在派生类中跳过实现。
所以问题是——如何在抽象类层面上指定方法返回泛型类型的构造函数,并且我可以跳过在子类层面对该方法的实现?或者也许我在抽象类层面上没有正确指定返回签名?
编辑:
请检查这个奇怪的问题。A类和B类的区别只是是否有显式构造函数。而在RealA中不起作用,而RealB中的getModel()方法却能正常工作。
class A {
a = '';
constructor(a: string) {
}
}
class B {
a = '';
static test(): void {
console.log('I do work');
}
}
abstract class Base<T> {
Prop: T;
constructor(TCreator: { new (): T; }) {
this.Prop = new TCreator();
}
getModel(): (new () => T) {
throw new Error('Method not implemented.'); // Error because don't know how to fix it
}
}
class RealA extends Base<A> {
getModel(): typeof A { // doesn't work - compilation error
return A;
}
}
class RealB extends Base<B> {
getModel(): typeof B { // works
return B;
}
}
var test = new RealA(A); // compile error
var test2 = new RealB(B)
对于 RealA 类,同样的错误
() => typeof A' is not assignable to type '() => new () => A'
答案#1
该错误是预期中的,因为类 A 的构造函数有一个必需的参数。抽象类要求构造函数在传递时不能有参数 (new() => T)。
简单的解决方案是移除 A 的构造函数。
如果你想能够传入那些构造函数需要参数的类,你将需要更改基类的定义以捕获构造函数类型,并让constructor接受那些必需的参数(在剩余参数中使用元组)
class A {
a = '';
constructor(a: string) {
}
}
class B {
a = '';
static test(): void {
console.log('I do work');
}
}
type ArgumentTypes<T> = T extends new (...a: infer A) => any? A : []
abstract class Base<T extends new (...a: any[])=> any> {
Prop: InstanceType<T>;
constructor(TCreator: T, ...a: ArgumentTypes<T>) {
this.Prop = new TCreator(...a);
}
getModel(): T {
throw new Error('Method not implemented.'); // Error because don't know how to fix it
}
}
class RealA extends Base<typeof A> {
getModel(): typeof A { // doesn't work - compilation error
return A;
}
}
class RealB extends Base<typeof B> {
getModel(): typeof B { // works
return B;
}
}
var test = new RealA(A, ""); // ok
var test2 = new RealB(B)
