Flowは静的型チェッカーです。コード内の一貫性のない型を検出し、アノテーションを使って明示的な型宣言を追加することができます。
-
トランスパイルの過程でBabelにFlowアノテーションを理解し削除させるため、
yarn add --dev babel-preset-flowを実行してBabelのFlowプリセットをインストールします。そして、package.jsonのbabel.presetsに"flow"を追加します。 -
プロジェクトのルートに空の
.flowconfigファイルを作ります。 -
yarn add --dev gulp-flowtypeを実行してFlowのGulpプラグインをインストールし、lintタスクにflow()を追加します:
import flow from 'gulp-flowtype';
// [...]
gulp.task('lint', () =>
gulp.src([
paths.allSrcJs,
paths.gulpFile,
paths.webpackFile,
])
.pipe(eslint())
.pipe(eslint.format())
.pipe(eslint.failAfterError())
.pipe(flow({ abort: true })) // Add Flow here
);abortオプションはFlowが問題を検出した場合にGulpタスクを中断させるものです。
これでFlowが実行できるようになりました。
src/shared/dog.jsにFlowアノテーションを以下のように追加します:
// @flow
class Dog {
name: string;
constructor(name: string) {
this.name = name;
}
bark(): string {
return `Wah wah, I am ${this.name}`;
}
barkInConsole() {
/* eslint-disable no-console */
console.log(this.bark());
/* eslint-enable no-console */
}
}
export default Dog;// @flowコメントはFlowにこのファイルの型検査をしてほしいことを伝えるものです。それ以外の部分について、Flowアノテーションは、たいてい関数の引数か関数名のあとにコロンがついています。詳細はドキュメントを見てください。
この状態でyarn startを実行すると、Flowは問題なく動きますが、ESLintはここで使われている標準的ではない文法について注意してくれることでしょう。Babelのパーサは先ほどインストールしたbabel-preset-flowプラグインのおかげでFlowコンテンツをパースできるようになるため、ESLintがFlowアノテーションを独自に解釈しようとするのではなく、Babelのパーサを使うようになってくれると理想的です。babel-eslintパッケージを使えばこれが実現できます。やってみましょう。
-
yarn add --dev babel-eslintを実行します。 -
package.jsonのeslintConfigに次のプロパティを追加します:"parser": "babel-eslint"
yarn startを実行するとlintと型検査が正しく行われるようになったはずです。
これでESLintとBabelで共通のパーサを実行できるようになったので、eslint-plugin-flowtypeを使ってESLintにFlowのアノテーションをlintさせられるようになりました。
yarn add --dev eslint-plugin-flowtypeを実行し、package.jsonのeslintConfig.pluginsに"flowtype"を追加します。また、eslintConfig.extendsの配列の"airbnb"の次に"plugin:flowtype/recommended"を追加します。
これで例えばname:stringというアノテーションを書くと、ESLintはコロンの後ろにスペースを入れるのを忘れていると注意してくれるようになります。
注意: package.jsonに書いた"parser": "babel-eslint"プロパティは実際には"plugin:flowtype/recommended"に含まれるものなのでpackage.jsonから削除することができますが、好みで明示的に残しておいても構いません。このチュートリアルは最小限のセットアップを行うものなので、削除しました(訳注:削除してない??)。
src以下のすべての.jsと.jsxファイルに対して、// @flowを追加し、yarn testまたはyarn startを実行します。そしてFlowが提案した部分全部に対して、型アノテーションを追加します。
直感的ではない例としては、src/client/components/message.jsxにある以下のものがあります:
const Message = ({ message }: { message: string }) => <div>{message}</div>;このように、分割代入している場合、オブジェクトリテラル記法のようなものを使って展開されたプロパティにアノテーションをつけます。
他に見かける例としては、src/client/reducers/dog-reducer.jsにあるように、FlowはImmutableがデフォルトのexportをつけないと注意してくるというものがあります。この問題はImmutableの#863で議論されていますが、2つの回避策があります:
import { Map as ImmutableMap } from 'immutable';
// or
import * as Immutable from 'immutable';Immutableがこの件を公式に解決するまで、Immutableコンポーネントをimportする時はどちらか好きな方を使いましょう。個人的にはimport * as Immutable from 'immutable'の方が、短い上に修正された際のリファクタリングも不要なので気に入っています。
注意: Flowが型エラーをnode_modulesフォルダで見つけた場合、問題のあるパッケージを無視するため[ignore]セクションを.flowconfigに追加します(node_modulesディレクトリ全体を無視しないようにします)。以下のようになります:
[ignore]
.*/node_modules/gulp-flowtype/.*
この場合、node_modules/gulp-flowtypeディレクトリにあるAtomのlinter-flowプラグインに型エラーが検出されました。これは// @flowがついたファイルを同梱していました。
これでlintされて、型検査もテストも通った万全のコードができました!
(原文: 12 - Flow)