首页 > 解决方案 > 为什么这个泛型函数的类型参数不接受给定的类型?

问题描述

我想在一个子类和一个生成器上指定一些数据的形状,该生成器使用一些通用T的 . 我最初的想法是使用下面的泛型(简化示例),但是当我调用makeMyClass和返回时new classRef,它给了我以下错误:

Type 'T' is not assignable to type 'DataInterface'

为什么不是Ttype DataInterface

class MySuperClass<T> {
  constructor(public data: T) {}
}

interface DataInterface {
  name: string;
}

let initData: DataInterface = {
  name: "Alice"
};

class MyClass extends MySuperClass<DataInterface>{ 
  constructor(public data: DataInterface) {
    super(data)
  }
}

function makeMyClass<T>(classRef: typeof MySuperClass): MySuperClass<T> {
    return new classRef(initData);
}

let a = makeMyClass<DataInterface>(MyClass);
let b = a.data

标签: typescriptgenericsfactory

解决方案


好吧,您的代码中有两个问题。首先是您将其定义makeMyClass为泛型,但随后您new classRef使用具体变量进行调用。这意味着它T不能是任何东西,它必须是 type type initData

除此之外,您将声明classRef为类的类型。最好将其定义为构造函数签名,否则您将遇到问题let a = makeMyClass<>(MyClass)

您的代码将适用于这些更改:

function makeMyClass<T>(classRef: new(initData: T) => MySuperClass<T>, initData: T): MySuperClass<T> {
    return new classRef(initData);
}

let a = makeMyClass(MyClass, initData);
let b = a.data

签名的new(initData: T) => MySuperClass<T>意思是,*一个接受 T 类型参数的构造函数,并创建一个类型为 的对象MySuperClass<T>。两者都MySuperClass<DataInterface>符合MyClass这个要求。但是,您会发现它MyClass不能分配给 type 的参数typeof MySuperClass。此外,构造函数类型的使用将限制您可以传递给具有该确切签名的构造函数的类型。如果您创建一个新的派生类,MySuperClass但它有一个带有两个参数的构造函数,则无法将它与此函数一起使用,因为它需要一个只需要一个 type 参数的构造函数T。这可以防止运行时错误,因此您不能调用参数少于预期的构造函数。

当然,如果你希望函数是泛型的,你需要传递 type 的第二个参数T来传递给类的构造函数。否则,正如我所解释的,该函数不能真正是通用的,因为它仅限于initData.


推荐阅读