facebook flow を触ってみただけのメモ

雰囲気の現状確認

今回は Flow | A static type checker for JavaScript について少し触った感触をメモる。altJS界隈に明るくはないので小並感。

flowtype の概観

  • flow 本体は型チェックのみ行う
  • Type Annotation の削除や harmony (ES6) の変換は react-tools を併用する
  • harmony (ES6) 変換は内部的に jstransform が使われる

自分の場合、ES6のついでに型チェックなのか、型チェックのついでにES6なのか分からない用法になりそうだが型チェックとES6準拠の拡張相当がそれぞれ独立しているのは好ましい。

インストールは Getting Started のとおりにzipを落としてきて実行ファイルに PATH を通すか、Mac なら brew install flow すればいい。あと flow init な。

型チェックの振る舞い確認

まずはスタンダードな感じで引数と戻り値に型を指定してみる。

/* @flow */
function foo(str: string) {
  return str + ' World!';
}
foo(123);

function world(): string {
  return 123;
}
world();

// path/to/flowtype.js
// line 5 col 7 number - This type is incompatible with
// line 2 col 20 string
// line 8 col 10 number - This type is incompatible with
// line 7 col 18 string

もちろん期待どおり。Android Javaやったおかげで真面目に型い言語のノリが分かるようになった気がする。よかったよかった。外部ライブラリは Declarations で補える。

型推論も確認してみる

Facebook Flowの初見の感想 - Qiita で褒められていた型推論も手元で動かしてみた。

/* @flow */
function product(...nums) {
  return nums.reduce((p, c) => p * c, 1);
}
product(1, 2, '3');

// /path/to/flowtype.js
// line 5 col 15 string - This type is incompatible with
// line 3 col 32 number

おー。TypeScript も素通りしてきたので素直な感動しかない。無駄にES6を絡めても問題ない。

jstransform の ES6 状況

flow関係ないけど https://github.com/facebook/jstransform/tree/master/visitors を見る限りでは次のような機能に対応していそう。ハッキリしたドキュメントが見当たらなかった。分かりやすい恩恵がありそうなものは、サポートされている。

  • arrow function
  • class
  • destructuring
  • object concise method
  • object short notation
  • rest param
  • template
  • rest property (es7)
  • spread property (es7)

引数・戻り値の型や、Class のフィールド型、ジェネリクスなどの型付け関係を脱がせば、ES6を部分サポートしたふつーのJavaScriptになっているだけなので抵抗が少ない。むしろ良い感じ。

gulp で実行してみたとき

gulp-flowtypegulp-react の組み合わせで、一見して問題なかった。

gulp.task('flowtype', function() {
  var react = require('gulp-react');
  var flow  = require('gulp-flowtype');

  return gulp.src('./src/flowtype.js')
    .pipe(flow({
      all: false,
      weak: false,
      declarations: './declarations',
      killFlow: false,
      beep: true
    }))
    .pipe(react({ stripTypes: true, harmony: true }))
    .pipe(gulp.dest('./dist'));
});

react-tools の harmony オプションを false にして別のトランスパイラにパイプするってのもアリだとは思う。ただ、flow がサポートしてない文法や宣言を行うとエラーが吐かれる。

/* @flow */
let x = 666;

// /path/to/flowtype.js
// line 2 col 1 - Unsupported variable declaration: let
// line 2 col 5 var x - Unknown global name

こんな感じ。これの後ろに評価可能なJSが続いていればそれもチェックしてもらえてるっぽいけど、どれくらいやってもらえるのかは不明。パースエラーでコケる感じではないっぽいので、表示の抑制とかで済む話なのかなぁ。

参考

altJS界の見解を参考にした。

そろそろ次の戦い(仕事)に向けて、これまで横目に見てきたものを良いものと悪いものに振り分けている最中。前回の戦いは AngularJS と express という構成にした結果、あまり楽しめずアウトプットが捗らなかったのでリベンジを誓いたい。