ts-learnings/08_type_inference.md

76 lines
4.6 KiB
Markdown
Raw Normal View History

2019-03-27 11:20:25 +08:00
# 类型推导
**Type Inference**
## 简介
本章节将涵盖TypeScript中的类型推导。也就是说这里将讨论类型在何处及如何被推导。
## 类型推导基础
在TypeScript中有好几个地方都使用到类型推导来处理那些没有显式类型注解explicit type annotation用于提供类型的信息。比如在下面的代码中
```typescript
let x = 3;
```
变量`i`的类型,就被推导为`number`。这种推导是在对变量及成员进行初始化、参数默认值的设置setting parameter default values以及确定函数返回值类型等期间发生的。
大多数情况下,类型推导都是直截了当的。在下面部分中,将对类型是如何进行推导的细微之处,进行探讨。
## 最优通用类型Best common type
当类型推导是从几个表达式生成的时,这些表达式的类型,就被用作计算出一个“最优通用类型”。比如:
```typescript
let x = [0, 1, null];
```
为推导出上面示例中`x`的类型,就必须考虑各个数组元素的类型。这里给到的该数组类型有两个选择:`number`与`null`。 **最优通用类型算法** 就对各个候选类型加以考虑,并选取那个兼容所有其它候选项的类型( **the best common type algorithm** considers each candidate type, and picks the type that is compatible with all the other candidates
因为必须要从所提供的候选类型选出最优通用类型,那么就有着某些候选类型共享一个通用结构,却并存在一个作为所有候选类型超集的类型的情况。比如:
```typescript
let zoo = [new Rhino(), new Elephant(), new Snake()];
```
理想情况下,可能希望将`zoo`推导为一个`Animal[]`,但因为该数组中没有对象是严格的`Animal`类型,所以无法做出有关该数组元素类型的推导。为了纠正这一点,就要在没有一种类型是其它候选类型的超类型时,提供显式地提供一个类型:
```typescript
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”。上下文类型赋予是在某个表达式的类型由其所处位置所决定时发生的。比如
```typescript
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包含了显式的类型信息那么上下文类型将被忽略。也就是像下面这样写上面的示例
```typescript
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。在最佳通用类型中上下文类型也扮演了一种候选类型。比如
```typescript
function createZoo(): Animal[] {
return [new Rhino(), new Elephant(), new Snake()];
}
```
在此示例中,最佳通用类型有着四种候选类型的集合:`Animal`、`Rhino`、`Elephant`以及`Snake`。其中`Animal`可能会被最佳通用类型算法选中。