ts-learnings/08_type_inference.md
2019-03-27 11:20:25 +08:00

4.6 KiB
Raw Blame History

类型推导

Type Inference

简介

本章节将涵盖TypeScript中的类型推导。也就是说这里将讨论类型在何处及如何被推导。

类型推导基础

在TypeScript中有好几个地方都使用到类型推导来处理那些没有显式类型注解explicit type annotation用于提供类型的信息。比如在下面的代码中

let x = 3;

变量i的类型,就被推导为number。这种推导是在对变量及成员进行初始化、参数默认值的设置setting parameter default values以及确定函数返回值类型等期间发生的。

大多数情况下,类型推导都是直截了当的。在下面部分中,将对类型是如何进行推导的细微之处,进行探讨。

最优通用类型Best common type

当类型推导是从几个表达式生成的时,这些表达式的类型,就被用作计算出一个“最优通用类型”。比如:

let x = [0, 1, null];

为推导出上面示例中x的类型,就必须考虑各个数组元素的类型。这里给到的该数组类型有两个选择:numbernull最优通用类型算法 就对各个候选类型加以考虑,并选取那个兼容所有其它候选项的类型( the best common type algorithm considers each candidate type, and picks the type that is compatible with all the other candidates

因为必须要从所提供的候选类型选出最优通用类型,那么就有着某些候选类型共享一个通用结构,却并存在一个作为所有候选类型超集的类型的情况。比如:

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

理想情况下,可能希望将zoo推导为一个Animal[],但因为该数组中没有对象是严格的Animal类型,所以无法做出有关该数组元素类型的推导。为了纠正这一点,就要在没有一种类型是其它候选类型的超类型时,提供显式地提供一个类型:

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

而在找不到最佳通用类型时推导结果就是联合数组类型the union array type(Rhino | Elephant | Snake)[]

上下文的类型Contextual Type

在TypeScript中类型推导在某些情况下还以“其它方向”起作用Type inference also works in "the other direction" in some cases in TypeScript。这就是所谓的“上下文的赋予类型contextual typing”。上下文类型赋予是在某个表达式的类型由其所处位置所决定时发生的。比如

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

为了从上面的代码中检查出错误TypeScript的类型检查器使用了window.onmousedown函数的类型类推导该赋值语句右侧的函数表达式的类型For the code above to give the type error, the TypeScript type checker used the type of the window.onmousedown function to infer the type of the function expression on the right hand side of the assignment。在其这样做的时候就能够推导出mouseEvent参数的类型。而假如该函数表达式并不是在一个上下文类型赋予位置not in a contextually typed position那么参数mouseEvent将有着类型any,从而不会出现任何错误。

而如果上下文类型赋予的表达式the contextually typed expression包含了显式的类型信息那么上下文类型将被忽略。也就是像下面这样写上面的示例

window.onmousedown = function (mouseEvent: any) {
    console.log(mouseEvent.button); // <- Now, no error is given
};

参数上带有显式类型注记的函数表达式,将覆盖上下文类型。而一旦这样做,就不会报出错误了,因为应用没有上下文类型特性。

在很多情况下上下文类型赋予都得以应用。常见的包括函数调用的参数、赋值语句的右侧、类型断言、对象的成员与数组字面值以及返回语句等Contextual typing applies in many cases. Common cases include arguments to function calls, right hand sides of assignments, type assertions, members of object and array literals, and return statements。在最佳通用类型中上下文类型也扮演了一种候选类型。比如

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

在此示例中,最佳通用类型有着四种候选类型的集合:AnimalRhinoElephant以及Snake。其中Animal可能会被最佳通用类型算法选中。