1. 基础
  2. 最佳通用类型
  3. 上下文类型

1. 基础

在 TS 中未明确指出类型的地方,TS 会帮助提供类型,当初始化变量和成员,设置默认参数值和决定函数返回值会发生这种自动推断,如变量 x 的类型被推断为 number

  1. let x = 3;

2. 最佳通用类型

类型推断会尽量考虑到所有可能的候选类型,并给出兼容所有候选类型的类型。下例中存在两种可能:numbernull

  1. let y = [0, 1, null];

因为在第一篇介绍基础类型时就提到过:用 null 赋值给其他类型,默编译通过不报错:

  1. let num: number = 3
  2. num = null

所以 y 的类型被推断为 number[]

再看一个例子,由于通用类型取自提供的候选类型,而候选类型共享了通用类型,这里我们希望能自动推断为 Animal 类型,但是大多数类型推断都是直截了当的,而数组里没有对象是 Animal 类型,所以找不到最佳通用类型,变量 food 会被推断为联合类型 (Dog | Cat | Fish)[]

  1. class Animal { }
  2. class Dog extends Animal { }
  3. class Cat extends Animal { }
  4. class Fish extends Animal { }
  5. let food = [new Dog(), new Cat(), new Fish()];

拯救的方法也很简单,手动明确地指出类型即可:

  1. let food: Animal[] = [new Dog(), new Cat(), new Fish()];

3. 上下文类型

TS 的类型推断也可能会反向进行,这叫“按上下文归类”,如下所示

  1. window.onmousedown = function(mouseEvent) {
  2. console.log(mouseEvent.button); // 报错
  3. };

这个函数表达式有明确的参数类型注解时,上下文类型会被忽略(屏蔽):

  1. window.onmousedown = function(mouseEvent: any) {
  2. console.log(mouseEvent.button); // 不报错
  3. };

上下文(context)其实就是根据语境来推断,所以很多情况都会用到,比如函数的参数,赋值表达式的右边,类型断言,对象成员和数组字面量和返回值语句。我认为也不需要强记,像是 vscode 这种编辑器会给出必要提示的。

上下文类型也会做为最佳通用类型的候选类型之一,如下所示,显然 Animal[] 会做为最佳通用类型:

  1. function createFood(): Animal[] {
  2. return [new Dog(), new Cat(), new Fish()];
  3. }