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

时间:2018-05-04 21:48:48

标签: typescript generics factory

我想在子类和生成器上指定一些数据的形状,这些数据创建具有一些通用T的类。 我最初的想法是使用如下的泛型(简化示例),但是当我调用makeMyClass并且当我返回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

1 个答案:

答案 0 :(得分:0)

嗯,您的代码中有两个问题。第一个是您将makeMyClass定义为通用,但随后使用具体变量调用new classRef。这意味着T实际上可以是任何内容,它必须是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无法分配给typeof MySuperClass类型的参数。此外,使用构造函数类型将限制可以传递给具有该确切签名的构造函数的类型。如果你从MySuperClass创建一个新的派生类,但是它有一个带有两个参数的构造函数,那么它就不可能在这个函数中使用它,因为它需要一个只需要一个类型为{的参数的构造函数{1}}。这可以防止运行时错误,因此您无法调用参数少于预期的构造函数。

当然,如果您希望函数是通用的,则需要传递类型为T的第二个参数,以传递给类的构造函数。否则,正如我所解释的那样,该函数实际上不是通用的,因为它仅限于T的类型。