为什么这个泛型函数的类型参数不接受给定的类型?

Why doesn't the type parameter of this generic function accept the given type?

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

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

为什么 T 不是 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

嗯,你的代码有两个问题。首先是您将 makeMyClass 定义为泛型,然后您使用具体变量调用 new classRef。这意味着 T 不能是任何东西,它必须是 type initData.

类型

除此之外,您将 classRef 声明为 class 的类型。最好将其定义为构造函数签名,否则 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 不能分配给 typeof MySuperClass 类型的参数。此外,构造函数类型的使用将限制您可以传递给具有该确切签名的构造函数的类型。如果您从 MySuperClass 创建一个新的派生 class 但它有一个带有两个参数的构造函数,则无法将它与此函数一起使用,因为它期望一个只需要一个参数的构造函数输入 T。这可以防止运行时错误,因此您不能调用参数少于预期的构造函数。

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

的类型