【问题标题】:Return constructor of generic type in TypeScript在 TypeScript 中返回泛型类型的构造函数
【发布时间】:2019-05-04 00:47:03
【问题描述】:

我正在努力定义如何编写 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'

【问题讨论】:

  • 您能否发布一个完整的示例。似乎适用于您提供的内容:typescriptlang.org/play/…
  • 看起来您的 T 是构造函数类型,而不是出于某种原因的实例类型。请注意User 类型和User 值不同,typeof User 类型与User 类型不同。您应该发布minimal reproducible example 以便有人准确指出问题。
  • @TitianCernicova-Dragomir 请检查最初的问题。我更新了。
  • 不确定用例是什么,但作为旁注 - 您可以只在基类中使用 getModel() { return this.constructor; } 而不是在每个派生类中实现它

标签: javascript typescript generics typescript-generics


【解决方案1】:

由于类A 的构造函数有一个必需的参数,因此该错误是预期的。抽象类将构造函数限制为没有参数 (new () =&gt; 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)

【讨论】:

  • 现在很有意义。如果他们提出这个错误或类似的解释会更容易吗?万分感谢。会想办法解决。它们可能都不适用,因为我们不能使用 any
  • @Selvatico 在这种情况下any 只是一个占位符,它是完全类型安全的,any 不会泄漏到类或实现的公共签名中。它只是告诉编译器构造函数可以返回任何类并且可以有任意数量的任何类型的参数。当您传入一个类时,该类将决定参数和实例类型,并且实际上不会存在任何内容。让我知道我是否可以提供更多帮助:)
猜你喜欢
  • 2019-09-19
  • 2019-09-03
  • 1970-01-01
  • 2021-10-06
  • 2010-10-16
  • 1970-01-01
  • 2016-04-05
  • 2018-07-09
  • 1970-01-01
相关资源
最近更新 更多