在TypeScript中返回泛型类型的构造函数

时间:2018-12-02 15:21:46

标签: javascript typescript generics typescript-generics

我正在努力定义如何编写TypeScipt代码,该代码表示​​该函数返回泛型类型的构造函数。周围有很多关于如何传递泛型类型的构造方法的示例,而不是如何返回的示例。

请检查以下示例:

这是抽象类的一部分:

 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 个答案:

答案 0 :(得分:1)

由于类A的构造函数具有必需的参数,因此会出现该错误。抽象类将构造函数传递给它,使其没有参数(new () => T)。

简单的解决方案是将构造函数删除到A

如果要传递具有要求参数的构造函数的类,则需要更改基类的定义以捕获构造函数类型,并让constructor接受那些必需的参数(在rest parameters中使用元组

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)