JavaScript
flow
TypeScript
React
babel

既存Reactプロダクトにbabel7と@babel/preset-typescriptを使ってFlowとTypeScriptを共存させる方法

現状について

もともとはPropTypesを使っていたReactのプロダクトだったんだけど、Flowを導入し始めていました。なので、Flowを使っているところとPropTypesを使っている部分が混在している状態です笑

ただ、実際はもともとFlowを入れたかった訳ではなく、本当はTypeScriptに移行したかったんですよね。なんでかというと、FlowだとBuidが通ってしまうから。

lint-stagedを使ってcommit時にチェックする方法もあるけど、TypeScriptの方がそもそもエラーあるとビルド通らないしいいなと。

babel7の@babel/preset-typescriptの登場

babel7によりTypeScriptのコードをJavaScriptにパースすることができ、なおかつ@babel/preset-typescriptによりFlowと同じように型情報を取り除くこともできるようになりました。

Flow廃止してTypeScriptに以降したいけど、結構苦行だよね?ってことで二の足を踏んでいたんですが、babel7の@babel/preset-typescriptの登場により一旦共存をさせてから徐々に以降できるんじゃない?ってことで試してみる価値はありそうってことでやってみました。

結論から言って共存は可能でした。とりあえずやり方は以下で!

インストール

$ npm install --save-dev @babel/preset-typescript typescript

.babelrc

一旦でも共存という道を選んでいるのでかなり気持ち悪い状態汗

{
  "presets": [
    "@babel/typescript",
    "@babel/preset-env",
    "@babel/preset-flow",
    "@babel/preset-react"
  ],
  "plugins": [
    "@babel/plugin-proposal-class-properties",
    "@babel/plugin-proposal-object-rest-spread",
    "react-hot-loader/babel",
    "@babel/plugin-proposal-optional-chaining"
  ]
}

webpack.config.js

babel-loaderのtestを変更する

{
  test: /\.(ts|js)x?$/,
  exclude: /node_modules/,
  use: ['babel-loader']
}

buildしてみる

適当にtsのエラーになるように仕込んでbuildしてみます。

が、

build通ってしまいます。

IntelliJ側ではTSエラー出ているのにbuildが通ってしまいます。多分なんですけどpreset-flowとpreset-reactがあるとbuild自体は通ってしまうようです。

エディタではエラーになっているのでいいっちゃいいのですが、できればエラーがある場合はbuild通らないようにしたい。というか、build通るならFlowでいいじゃん。

エラーがあったらbuildを通さないようにする

以下のプラグインのasync: falseにすることで、webpackの出力をブロックして、TypeChecker/linterを待機させてWebpackのコンパイルにエラーを追加することができます。

Realytics/fork-ts-checker-webpack-plugin: Webpack plugin that runs typescript type checker on a separate process.

$ npm install --save-dev fork-ts-checker-webpack-plugin

webpack.config.js

plugins: [
  new ForkTsCheckerWebpackPlugin({ async: false }),
]

これでbuildが通らなくなりました。一旦望み通りの挙動にすることができた感じです。

tslint & prettier

うまく動かないかなと思ったけど、割とうまく行くのでお好みで設定すれば良さそうです。

$ npm install --save-dev tslint tslint-config-prettier tslint-config-standard tslint-plugin-prettier

まとめ

FlowとTypeScriptを共存させてしまっている状態ですごく気持ち悪いですね。ただ今後の以降方針としては

  • Flowを使っているところからTypeScriptに移行
  • Flowの設定外す
  • ほかjsファイルをtsファイルへ
  • babel/preset-typescriptはやめてts-loaderへ

@babel/preset-typescriptを使うことでというように一つクッションを置くことができるんじゃないかなと思います。ただ、新規でプロジェクトやる場合はTypeScript一択ですけどね笑