2018.04.19

TypeScriptのユーザがFlowを使ってみた感想

  • このエントリーをはてなブックマークに追加
  • follow us in feedly

 SuPICEではTypeScriptを用いて開発をしています。著者である私もTypeScriptのユーザです。 (今更感がありますがTypeScriptは静的に型の検査を行うAltJSです)静的な型の検査というとFlow typeも挙げられると思います。最近個人的にFlowを使う機会が手に入りました。 丁度良い機会なのでTypeScriptのユーザがFlowを使用してみての感想を書いていこうと思います。

開発環境

 Visual Studio Codeで使う分にはどちらもさほど差がないように感じます。定義へ移動。関数や変数の説明の表示、補完、etc.。個人的にやって欲しいことは大体やってくれています。Visual Studio Code優秀ですね。

DefinitelyTypedとFlow-typed

 型定義のレポジトリですね。最初DefinitelyTypedと比べてFlow-typedは質が高そうなイメージがありました。(「a collection of high-quality library definitions」とか言ってますし...)しかし「Genericsを使えば回避できそうなのにany使ってる」とか物足りないものはやっぱり存在しました。Flow-typedで完全に動かないというものにはまだ遭遇していないので、確かに品質は良いのかもしれません。でも正直どっちもどっちだなというのが感想です。数に関しては絶対的にDefinitelyTypedの方が多いです。実際に大まかに数を数えてみたところ、2017/3/9現在で「Flow-typed 約230、DefinitelyTyped 約2940」(※1)となりました。既にメンテされていないものや、バージョンごとの重複などもある(少なくともflow-typedにはありました)ので正確な数字ではないかもしれませんが、10倍以上の差があることが分かります。TypeScriptよりFlowの方がサードパーティのライブラリの型は自力で書かなければいけないケースが多いかもしれませんね。(Reactだとかaxiosだとかlodashだとか有名どころのライブラリは大体あるので特に気にしなくてもよいかもしれません。)

ドキュメント

 TypeScriptと比較してFlowはドキュメントにない内容が多い印象があります(特にUtility Type)。分からないならソースを直接見ろという姿勢は嫌いではないですが、 ちょっと使ってみるという時には不便です。後OCamlで書かれているのも辛さがあります。TypeScriptと比べてソースを読むハードルが格段に高いです。 TypeScriptのソースもJavaScriptです。いざ問題が発生した際にOcamlのFlowよりは楽にソースを追えるのではないでしょうか。

Generator

 TypeScriptはyieldに関しての型定義ができません。Generatorを使うならFlow一択だと思います。まぁでもRedux-sagaとか使わない限りGenerator自体使う機会はなさそうな気がしますが...

union type

 union type(A | Bのようなやつ)に関してです。どちらか片方の型にしかないプロパティやメソッドを使いたい場合、片方の型でしかこの処理は行われないことを示してやらなければなりません(disjoint)。 TypeScriptの方がdisjointに関しては楽でした。基本的にどちらもtypeofやliteral、instanceofを使ってdisjointしますが、 サードパーティのライブラリを使うときなど、それだけでは上手くいかないケースも多いです。TypeScriptの方が容易にcastが行えますし、最悪User Defined Typeを使うという回避策があります。 頑張れば似たようなことをFlowでもできますが、cast用の関数を作ってやったりなどが必要で結構面倒です。(そもそもunion typeは基本的に避けるべきだと思われるので、あまり考慮に入れる必要はないかもしれませんが...)

ソース. FlowとTypeScriptのcastの仕方の違い

// 定義が一部古くて書き換えたい
import temp from 'moduleA';

// Flowの場合、cast用の関数を作る必要がある
export function castToA(arg: any):InterfaceA {
  return arg;
}
const castedTemp: InterfaceA = castToA(temp);

// TypeScriptの場合は1行
const castedTemp = (temp as any) as InterfaceA;

 ざっと使ってみた感想は以上です。確かに差はありましたが、どちらが良いか決定づけられる程大きなものはないように感じました。巷ではFlowを推している人が多い印象があります。確かに以前はTypeScriptはnullが非許容にできないとか、unionがdisjointできないとか色々ありました。しかし2系になってから問題の大半は改善されましたし、Mapped Typesのような非常に強力な機能もversion 2.1.4以降で追加されていきました。今現在新しく選べというなら慣れの問題もあるので著者はTypeScriptを選ぶと思います。しかし今後追加される機能次第では気持ちが揺らぐかもしれません。これからもTypeScriptとFlowからは目が離せませんね。

※1 DefinitelyTypedは「DefinitelyTyped/」のディレクトリ数、Flow-typedは「flow-typed/cli/flow-typed/npm/ + flow-typed/definitions/npm/」のディレクトリ数を計測

資料ダウンロード

2 件

関連する記事