一、基础

TypeScript 中没有明确指定类型的地方,类型推论会尝试给出类型,比如:

const x = 3;

此时,类型推论会发生在初始化变量和成员的时候、设置默认参数值和决定函数的返回值的时候

变量 x 类型被推断为 number

二、最佳通用类型

当需要从几个表达式中推断类型的时候,会使用这些表达式的类型来推断出一个最合适的通用类型,比如:

let x = [0, 1, null];

此时为了推断 x 的类型,需要遍历整个数组的所有元素的类型。从遍历结果看有两个选择,分别是 numbernull计算通用类型算法会考虑所有的候选类型,并给出一个兼容所有候选类型的类型。

因为最终的通用类型也是来自候选类型,有时候候选类型共享相同的通用类型,但是却没有一个类型能够为所有候选类型所兼容,比如:

let zoo = [new Rhino(), new Elephant(), new Snake()];

上面的数组中,如果有个 Animal ,并且是上面三个 class 的基类,则可以作为最佳通用类型。但是没有找到最佳通用类型,类型推断的结果成为联合数组类型:(Rhino | Elephant | Snake)[]

三、上下文类型

TypeScript 的类型推断也可能按照相反的方向进行,称为 按上下文归类。按上下文归类会发生在表达式的类型与所处的位置相关时。

window.onmousedown = function(mouseEvent: number) {
    console.log(mouseEvent.button);  //<- Error
};

上面代码中会报错如下:

1.jpg

而此时如果将 mouseEvent 类型声明为 any 则是 OK 的,因为对于 window.onmousedown 根据上下文推断 mouseEvent 参数的类型不可能是 number,如果不声明 mouseEvent 的类型,则会推断成 any ,而此时如果声明是 any 则也不会报错。

window.onmousedown = function(mouseEvent: any) {
    console.log(mouseEvent.button); 
};

如果明确声明了参数类型,则会忽略上下文的类型

上下文类型会在很多情况下使用到。 通常包含函数的参数、赋值表达式的右边、类型断言、对象成员和数组字面量和返回值语句。 上下文类型也会做为最佳通用类型的候选类型。比如:

function createZoo(): Animal[] {
    return [new Rhino(), new Elephant(), new Snake()];
}

上面从上下文中推断出了 Animal 是最合适的最佳候选类型。