打字稿泛型 class、方法参数和方法 return 类型

typescript generics class, method parameter and method return type

我有这个功能

function getCollection<T>(collectionType: T): Collection<T> {
  return new Collection<T>()
}

Collection class 我有这个

export class Collection<T> {
  public add (item: T) {
    // .. logic
  }
}

我有一个这样定义的用户class

export class Student {

}

当我尝试这样做时

getCollection(Student).add(new Student());

出现错误

TS2345: Argument of type 'Student' is not assignable to parameter of type 'typeof Student'.   Property 'prototype' is missing in type 'Student' but required in type 'typeof Student'.

以下工作正常。

new Collection<Student>().add( new Student());

那么函数returns泛型集合有什么问题呢?

这个错误是由于泛型类型是从参数推断出来的;这意味着 T 不是 Student 但实际上是 typeof Student。因此 return new Collection<T> 不像 return new Collection<Student> 而是 return new Collection<typeof Student>.

这可以通过实际为泛型参数分配类型来解决:

getCollection<Student>(Student)

上面使用了多余的参数,因此getCollection可以重构为:

getCollection<T>(): Collection<T> {
  return new Collection<T>("some-arg1", "some-arg2");
}

并被称为:

getCollection<Student>()

Link 到 playground.

T 实际上是 typeof Student 类型。 Student 是 class 的实例,而 typeof Student 是构造函数。要获取构造函数的实例类型,请使用直观命名的 InstanceType built-in:

public getCollection<T>(collectionType: T): Collection<InstanceType<T>> {
  return new Collection<InstanceType<T>>("some-arg1", "some-arg2")
}

但是现在你必须添加一个应该不是什么大问题的约束:

public getCollection<T extends new (...args: any[]) => any>(...

这应该导致:

public getCollection<T extends new (...args: any[]) => any>(collectionType: T): Collection<InstanceType<T>> {
  return new Collection<InstanceType<T>>("some-arg1", "some-arg2")
}