babel-plugin-typecheck を使って flowtype 文法で書かれたJSをランタイムチェックする


https://github.com/codemix/babel-plugin-typecheck を使ってみた。

これは何

babelでflowtypeの構文を使って型エラーのランタイムチェックを行う。静的解析ではない。(自分がドキュメントから見落としてるだけで静的解析を行う方法がある?)

興味を持った理由

  • 既存コードに対してtypescriptを導入するのは大変
  • flowtypeは既存コードからの乗り換えは簡単だが、型チェッカの挙動が未だに不審
  • コード上のドキュメントとしての型 + ランタイムチェックというアプローチなら十分では

ESdoc等で型を書いてもあくまでドキュメント上の指定だが、flow syntax とこれなら実行可能という点が大きい。最悪動かなくてもランタイムチェックを外せば良い。型指定はドキュメントとして残る。

Install

すでにbabel環境があることを想定

npm i -D babel-plugin-syntax-flow babel-plugin-transform-flow-strip-types babel-plugin-typecheck
.babelrc
{
  "presets": ["es2015"],
  "plugins": [
    ["typecheck", {
      "disable": {
        "production": true
      }
    }],
    "syntax-flow",
    "transform-flow-strip-types"
  ]
}

本番ではランタイムチェックを有効化しない。

browserify-railsの設定

browserify-rails を使ってる人はここで NODE_ENV を渡すことで無効化できた。

config/environments/production.rb
config.browserify_rails.node_env = "production"

コードを書いてみる

flowといえば口うるさいイメージがあったので、まず最初にそのまま実行してみた。無事巨大なコードベースで動作確認。

次に、エラーが起きるコードを書いてみた。

application.js
function f(name: string): number {
  return name.length;
}

f([1]);

ちゃんと開発環境でランタイムエラー出た。

別ファイルに書いた型定義の import type {...} form ... も上手く動いた。

感想

テストコードが十分にあればランタイムチェックで型違反が検知できる。アプリケーションをスクラッチで設計するときはtypescriptでいいだろうが、既存コードの書き換えならこっちもアリでは、という感じ。