TypeScript Handbook を読む (8. Type Inference)

[TypeScript Handbook](https://www.typescriptlang.org/docs/handbook/basic-types.html) を読み進めていく第八回目。

1. [Basic Types](http://qiita.com/murank/items/9c1f633545842c953947)
1. [Variable Declarations](http://qiita.com/murank/items/913f1c1e4e725047436c)
1. [Interfaces](http://qiita.com/murank/items/553276c3dc2eec9bfe47)
1. [Classes](http://qiita.com/murank/items/7e8f15225bc8259e9bf3)
1. [Functions](http://qiita.com/murank/items/e310ce68ed5a0058d42d)
1. [Generics](http://qiita.com/murank/items/144b686d34fd433a97a3)
1. [Enums](http://qiita.com/murank/items/cc487562b21bae3728ba)
1. Type Inference (今ココ)
1. [Type Compatibility](http://qiita.com/murank/items/606efb0615294a6826e3)
1. [Advanced Types](http://qiita.com/murank/items/bc1776efbecbd2120d94)
1. [Symbols](http://qiita.com/murank/items/04b3b31caa677750f240)
1. [Iterators and Generators](http://qiita.com/murank/items/7ceec53dde886f31a682)
1. [Modules](http://qiita.com/murank/items/0fc4e059be8ea5e1c274)
1. [Namespaces](http://qiita.com/murank/items/0dfad4a0bb91aaa6c97b)
1. [Namespaces and Modules](http://qiita.com/murank/items/0be1978a3515fc76e7ba)
1. [Module Resolution](http://qiita.com/murank/items/5f11466474d49498bbd5)
1. [Declaration Merging](http://qiita.com/murank/items/ec90ba04edab1ea3718e)
1. [JSX](http://qiita.com/murank/items/90164aa9a3bed3c49a80)
1. [Decorators](https://qiita.com/murank/items/580e34883e0832ca7aed)
1. [Mixins](https://qiita.com/murank/items/e77ad8359ed1fd82822d)
1. [Triple-Slash Directives](https://qiita.com/murank/items/faff57883338ebdeda12)
1. [Type Checking JavaScript Files](https://qiita.com/murank/items/588eaddfe8af59914658)


# Type Inference
[原文](https://www.typescriptlang.org/docs/handbook/type-inference.html)

## Basics
TypeScript では、型が明示されていない場合に型推論が行われるところが何箇所かあります。
以下の例では `x` の型は `number` と推論されます。

```ts:TypeScript
let x = 3;
```

このタイプの推論は、変数やメンバの初期化時、デフォルト引数の設定時、関数の戻り値の型の決定時に行われます。


## Best common type
複数の式に対して型推論が行われる場合、それらの式の "最適な共通型" が型として採用されます。

以下の例では、配列の各要素の型を基に `x` の型が推論されますが、各要素の型として `number` または `null` が考えられます。

```ts:TypeScript
let x = [0, 1, null];
```
>`--strictNullChecks` を指定していない場合、`null` を `number` に代入できるので `x` の型は `number[]` になる。
>`--strictNullChecks` を指定している場合、`null` を `number` に代入できないため、`x` の型は `(number|null)[]` になる。


最適な共通型は指定された型を基に選択されるため、以下の例では `zoo` の型が `Animal[]` として推論されてほしいと思うかもしれませんが、実際には各要素が `Animal` を継承したクラスではないのでそのようには推論されません。

```ts:TypeScript
let zoo = [new Rhino(), new Elephant(), new Snake()];
```

これを修正するためには型を明示することです。

```ts:TypeScript
let zoo: Animal[] = [new Rhino(), new Elephant(), new Snake()];
```
>まあ意図しない推論を予防するためにも、なるべく型は指定した方が良いだろうね

そして、最適な共通型が見つからなかった場合には共用配列型 (`(Rhino | Elephant | Snake)[]`) が採用されます。
>`any` とかになるわけではないのね


## Contextual Type
TypeScript は他にも "文脈に基づく型付け" と呼ばれる推論も行いますが、これは型推論が行われる場所に基づいて行われます。

以下の例はエラーになりますが、これは右辺が `Window.onmousedown` に代入可能な関数であることに基づいて、`mouseEvent` 引数の型が自動的に推論されるためです。

```ts:TypeScript
window.onmousedown = function(mouseEvent) {
    console.log(mouseEvent.buton);  //<- エラー。正しくは 'button'
};
```

ただし、明示的に型が指定されている場合には、文脈に基づく型付けは行われません。

```ts:TypeScript
window.onmousedown = function(mouseEvent: any) {
    console.log(mouseEvent.buton);  //<- エラーにならなくなる
};
```

文脈に基づく型付けは、最適な共通型の候補にもなります。
以下の例では最適な共通型として、`Animal`、`Rhino`、`Elephant`、`Snake` の中から `Animal` が選択されます。

```ts:TypeScript
function createZoo(): Animal[] {
    return [new Rhino(), new Elephant(), new Snake()];
}
```
>戻り値の型を明示してるけど、例として正しいんだろうか?