Flow導入時に最初にやることまとめ

備忘録的に。

## [flow-typed](https://github.com/flowtype/flow-typed/) をグローバルインストール

参考：[Flow | Checking third-party code](https://flowtype.org/docs/third-party.html#_)

`flow-typed` という CLI があり、package.json があるディレクトリでこのコマンドを使うと React などサードパーティのライブラリに対する型定義ファイルを探してダウンロードしてくれる。

```zsh
$ npm i -g flow-typed
```

これはプロジェクトごとではなく端末ごとに一度実行すれば OK。

## Flow をインストール

プロジェクトで

```zsh
$ npm i -D flow-bin
```

ついでに `flow` コマンドを使えるよう package.json に追記しておく。

```diff
   "scripts": {
     "webpack": "webpack --progress --colors --watch",
     "start": "webpack-dev-server --inline --hot",
+    "flow": "flow",
     "lint": "eslint src",
     "test": "echo \"Error: no test specified\" && exit 1"
   },
```

## 初期化（`.flowconfig` ファイルを作成）

```zsh
$ ./node_modules/.bin/flow init
```

プロジェクトルートに `.flowconfig` というファイルが生成されているはず。
`node_modules` を除外するように設定しておく。

```:.flowconfig
[ignore]
.*/node_modules/.*

[include]

[libs]

[options]
```

## Babel プラグインをインストール

トランスパイル時に Flow の型定義を取り除くために必要。

```
$ npm i -D babel-plugin-transform-flow-strip-types
```

```diff:webpack.config.js
         query:{
-          presets: ['react', 'es2015', 'react-hmre']
+          presets: ['react', 'es2015', 'react-hmre'],
+          plugins: ['transform-flow-strip-types'],
         }
```

## eslint-plugin-flowtype のインストール

https://github.com/gajus/eslint-plugin-flowtype
Flow の型定義つきの JS を ESLint に通すために必要。
parser を [babel-eslint](https://github.com/babel/babel-eslint) に変更する必要あり。

```zsh
$ npm i -D babel-eslint eslint-plugin-flowtype
```

```diff:.eslintrc
 {
+  "parser": "babel-eslint",
   "extends": "airbnb",
+  "plugins": ["flowtype"],
   "rules": {
     ...
   }
 }
```

## ESLint の `no-duplicate-imports` ルールを無効にする

参考：[no-duplicate-imports rule for Flow type imports · Issue #59 · babel/eslint-plugin-babel](https://github.com/babel/eslint-plugin-babel/issues/59)
`import type` で import する型定義のモジュール名と通常のモジュール名がかぶったときにエラーになってしまうので、無効にする。
なお同等のチェックは [eslint-plugin-import の no-duplicates](https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-duplicates.md) というルールでチェックされるので問題なし。

## eslint-plugin-flowtype のルールを調整

参考：[FlowtypeのUtility TypesでESLintエラーを出さないようにする - dackdive's blog](http://dackdive.hateblo.jp/entry/2017/04/18/232208)

そのままだと Flow の [Utility Types](https://flow.org/en/docs/types/utilities/)（`$Shape` とか）で `no-undef` エラーが出るため、 `.eslintrc` に以下を追記する。


```diff:.eslintrc
   "rules": {
      ...
+    "flowtype/define-flow-type": 1,
+    "flowtype/use-flow-type": 1,
   }
```

## flow-typed で Redux, react-redux の型定義ファイルをインストール

参考：[flow-typedで外部ライブラリの型定義を使う - Qiita](http://qiita.com/kuy/items/90fe63a9cc6710815c09)
こちらにあるように、

```
$ flow-typed search redux
```

で型定義ファイルを検索した後、

```
$ flow-typed install redux@3
```

のように `@` 以降でバージョンを指定しつつインストール。
（flow-typed@2.0.0 では `@` 以降の数字は省略できました）
実行すると `flow-typed/npm/` というディレクトリと、その下に定義ファイルが生成されている。

※または

```
$ flow-typed install
```

のように引数なしでインストールすると package.json を解釈して自動的に関係のある型定義をダウンロードしてくれるみたい。

```
• Found flow-bin@v0.39.0 installed. Installing libdefs compatible with this version of Flow...
• Found 20 dependencies in package.json. Searching for libdefs...
• flow-typed cache not found, fetching from GitHub...done.
• Installing 3 libdefs...
  • flow-bin_v0.x.x.js
    └> ./flow-typed/npm/flow-bin_v0.x.x.js
  • react-redux_v4.x.x.js
    └> ./flow-typed/npm/react-redux_v4.x.x.js
  • redux_v3.x.x.js
    └> ./flow-typed/npm/redux_v3.x.x.js
• Generating stubs for untyped dependencies...
  • file-loader@^0.9.0
    └> flow-typed/npm/file-loader_vx.x.x.js
  • babel-preset-es2015@^6.18.0
    └> flow-typed/npm/babel-preset-es2015_vx.x.x.js
  • babel-preset-react@^6.16.0
    └> flow-typed/npm/babel-preset-react_vx.x.x.js
  • babel-eslint@^7.1.0
    └> flow-typed/npm/babel-eslint_vx.x.x.js
 ```

なんかこんな感じでつらつらと出てくるはず。
ただし、`• Generating stubs for untyped dependencies...` 以下のファイルは型定義が存在しないパッケージのようで、Stub と呼ばれる無駄なファイルが大量に生成されてしまう。

この Stub を生成しないようなオプションが最近追加された？未確認。
[Add an option to skip stubs when installing by lime · Pull Request #686 · flowtype/flow-typed](https://github.com/flowtype/flow-typed/pull/686/files)

## 準備完了！

あとはプロジェクトに合わせて型を書いていく。
React/Redux 系プロジェクトだともう少し共通でやることがありそうなので、わかったら追記する。