Flowの導入と使い方 

# Flow とは

動的型付けのJavaScriptでも静的型付けができるようになる静的チェッカーです。
つまりJavascript でもTypescriptのように型宣言することができるようになります。

## Flow インストール
[こちらを参照](https://qiita.com/takanorip/items/603365d2471104ac7d51)

## Flow 有効
ファイルの一番上に 

```js
// @flow
```

を追加する。

## Flowのプリミティブ型

| 型 | 意味 |
| ------------ | ------------- |
| `any` | 静的チェック無効。何も書かないとこれ |
| `mixed` | 何の型でも受け取るが、利用時に型ごとに絞込が必要 |
| `*` (実存型) | 代入のたびに強制的な型推論を行う |
| `number` | 数値 |
| `boolean` | ブール |
| `string` | 文字列 |
| `'A' ｜ 'B' ｜ 'C'` | AかBかCのどれか|
| `Object` | オブジェクト|
| `{ id: number }` | id を持つオブジェクト |
| `Array<string>` | 文字列の配列|
| `Set<string>` | 文字列のSet  |
| `string[ ]` | 文字列の配列|
| `Function` | 関数 |
| `Class<User>` | Userクラス |
| `React.DOM` | React Element |
| `SyntheticInputEvent<EventTarget>` | React.DOMのEvent |

その他、膨大な数の型が載ってます。
https://www.saltycrane.com/flow-type-cheat-sheet/latest/

## Flow の特殊な型

### mixed
全ての型を代入できるが、利用するときはチェックが必要。

```js
let val: mixed;
val = {};
val = 1;
val = 'test';
if (typeof val === 'function') {
  val();
}
val(); // error
```


### * (実存型)
全ての型を代入できる。また、代入時に強制的に型推論される。

```js
let val: *;
val = 1;          // val is number 
val = 'test';     // val is string 
val = {};         // val is Object
val();            // Error occurs because val　is Object 
val = 1;          // val is number 
val.doSomething() // Error occurs because val is number
```

## Maybe ( ? )  の使い方

### null も undefined も許可しない
```js
let val: number;
val = 0;
val = undefined; // error
val = null; // error
```

### null と undefined を許可する
```js
let val: ?number;
val = 0;
val = undefined; 
val = null; 
```

### プロパティの必須有無

#### 必須プロパティあり
```js
let val: { id: number };
val = { id: 1 };
val = {  }; // error
```

#### 必須プロパティなし
```js
let val: { id?: number};
val = {id : 1};
val = { };
```

#### おまけ
必須プロパティなし。もしあった場合はnumberかnullかundefinedであること。

```js
let val: { id?: ?number };
val = { id: 1 };
val = { };
val = { id: null };
val = { id: undefined };
val = { id: 'string' }; // error 
```

## React + react-redux Component
e.g.

```js
import React from 'react';
import { connect } from 'react-redux';
import type { MapStateToProps } from 'react-redux';
import { Map } from 'immutable';
import type { Map as MapType } from 'immutable';
import { fetchUsers } from 'actions/users';

type Props = {
  users: MapType,
  selected: string,
};

type State = {
  selected: string,
};

export default class UserSelector extends React.Component<Props, State> {
  static defaultProps = {
    users: new Map()
  };
  constructor(props: Props) {
    super(props);
    this.state = { selected: props.selected };
  }
  componentWillMount() {
    this.props.fetchUsers();
  }
  componentWillReceiveProps(nextProps: Props) {
    if (nextProps.selected) {
      this.setState({ selected: nextProps.selected });
    }
  }
  render() {
    this.props.users.valueSeq().map(user => (
      <div>
        {user.get('id') === this.state.selected && <p>{user.get('name')} selected</p>}
        {user.get('id') !== this.state.selected && <p>{user.get('name')}</p>}
      </div>
    ));
  }
};

const mapStateToProps: MapStateToProps<*, *, *> = (state: *) => {
  return {
    users: state.users,
    selected: state.selected,
  };
};

const mapDispatchToProps = (dispatch: Dispatch<*>) => ({
  fetchUsers : () => dispatch(fetchUsers())
})

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(UserSelector);
```

## 外部ライブラリの型

e.g. flow-typed でライブラリを検索してインストールする。

```shell
(´ω`) < npm run flow-typed search moment

> my-project@1.0.0 flow-typed /src
> flow-typed "search" "moment"

• rebasing flow-typed cache...done.

Found definitions:
╔════════╤═════════════════╤══════════════╗
║ Name   │ Package Version │ Flow Version ║
╟────────┼─────────────────┼──────────────╢
║ moment │ v2.3.x          │ >=v0.34.x    ║
╟────────┼─────────────────┼──────────────╢
║ moment │ v2.x.x          │ >=v0.28.x    ║
╚════════╧═════════════════╧══════════════╝

(´ω`) < npm run flow-typed install moment@v2.3.x  --skip
```

e.g. package.json から依存ライブラリの型情報をまとめてインストールする。

```shell
(´ω`) < npm run flow-typed install --skip
```

## Learn more

[Try flow playground](https://flow.org/try/ )
[Flow cheatsheet](https://devhints.io/flow)
[Flow Type Cheat Sheet](https://www.saltycrane.com/flow-type-cheat-sheet/latest/)