为什么可以在不指定泛型类型参数的情况下实例化泛型类

时间:2021-03-06 08:18:27

标签: typescript class generics typescript-generics

我不明白为什么 TypeScript 允许在没有指定实际泛型类型参数的情况下实例化泛型类? 在以下示例中,类 Foo 具有泛型类型参数 T。 在行 const foo = new Foo() 中,可以创建一个新的 foo 对象而无需指定泛型类型参数。 foo 的类型为 Foo<unknown>bar 的类型为 valueType<unknown>

为什么有可能并且 TypeScript 不会引发错误? 这是什么用例? TypeScript 可以强制要求泛型类型参数吗?

type valueType<T> = {
   name: string,
   key: T|null,
};

class Foo<T> {
   private value: valueType<T>;

   public constructor() {
      this.value = {
         name: '',
         key: null,
      };
   }

   public setValue(value: valueType<T>) {
      this.value = value;
   }

   public getValue(): valueType<T> {
      return this.value;
   }
}

const foo = new Foo();
const bar = foo.getValue();

Typescript Playground Link

2 个答案:

答案 0 :(得分:1)

<块引用>

我不明白为什么 TypeScript 允许在没有指定实际泛型类型参数的情况下实例化泛型类?

在大多数情况下,泛型可以从参数中推断出来。在这种情况下,没有参数,因此必须明确设置或变为 unknown

假设我们修改了我们的构造函数,使其采用 key 类型的 T 作为参数。

public constructor(key: T) {

现在打字稿会自动为我们的实例分配泛型变量作为我们传递给构造函数的 key 参数的类型。我们不需要写new Foo<string>('x')。我们可以只写 new Foo('x') 并得到一个 Foo<string>

<块引用>

TypeScript 可以强制要求泛型类型参数吗?

我不这么认为,但我不确定。它会在您的 tsconfig 或 linter 中。

如果您要求每个泛型函数或类都需要一个明确声明的泛型,那么这会很快变得非常烦人。类型推断是 typescript 的基石之一。您只希望在推断为 unknown 的情况下需要它。

您通常会看到泛型函数和类为泛型设置了默认值,当无法推断时使用该默认值。 unknown 会产生问题,但 any 会起作用(只是不是很有帮助)。没有任何东西可以分配给 unknown,但一切都可以分配给 any。您可以将 any 设置为默认值:

class Foo<T = any> {

现在,当您调用 new Foo() 时,您会得到 Foo<any>

答案 1 :(得分:1)

在其他 similar threads 中推荐的合理选项是默认为 never 类型。这无疑会导致进一步的问题,因为 never 类型不能用于任何有意义的事情,因此您的类的调用者会意识到他们做错了什么,他们需要将类型参数传递给 Foo .

type valueType<T> = {
   name: string,
   key: T|null,
};

class Foo<T = never> {
   private value: valueType<T>;

   public constructor() {
      this.value = {
         name: '',
         key: null,
      };
   }

   public setValue(value: valueType<T>) {
      this.value = value;
   }

   public getValue(): valueType<T> {
      return this.value;
   }
}

const foo = new Foo();
// bar will now have the `never` type, making it unusable
const bar = foo.getValue();