Facebook Flowの初見の感想

[mizchi君の記事](http://qiita.com/mizchi/items/d50fbdd8c2dcd01c38f9)を見て、だいぶ感想が違ったので書くことにした。
なお、僕はTypeScript信者であることを踏まえてこの記事を読んでほしい。

あと、最初はまじめに記事にしようと思ったけどダルくなってきたのでメモをそのまま投げる。

## TypeScriptより良い型推論

Flowパイセンの一番偉いところはTypeScriptより型推論が強いところだと思った。[#](http://flowtype.org/#what-is-flow)

```js
/* @flow */
function foo(x) {
  return x * 10;
}
foo('Hello, world!');
```

```
$> flow
hello.js:5:5,19: string
This type is incompatible with
  hello.js:3:10,15: number
```

関数foo内部のxは、* 演算子を利用しているのでnumberであると推論している。
これが実際の利用箇所でstringを引数にしているので怒ってくれるわけだ。偉いな！
`Flow is a static type checker`と謳っているとおり、完全にpure JavaScriptで書かれているプロジェクトに対して、新しいlintの一種であるかのように導入できるのは大きなアドバンテージだろう。

なお、もちろん型注釈を明示的に与えることもできる模様。

```js
/* @flow */
function foo(x) {
  return x.reduce((p, c) => p + c.charAt(0), 0);
}

foo([false, true]);
```

```
$ flow check

/private/tmp/flow/hello.js:3:33,43: call of method charAt
Property not found in
  /private/var/folders/c8/yszwff5d4z57z0d4sn04yy140000gn/T/flow_vvakame/flowlib_7e8f1b7/lib/core.js:54:1,56:1: Boolean

Found 1 error
```

スゲェ。でもエラーメッセージわかりにくい。

## nullを許容しない

[ここ](http://flowtype.org/docs/five-simple-examples.html#3-nullable-types)より抜粋。

```js
/* @flow */

function length(x) {
  return x.length;
}

var total = length('Hello') + length(null);
```

```
03_Null/nulls.js:4:10,17: property length
Property cannot be accessed on possibly null value
  03_Null/nulls.js:7:38,41: null
```

nullを想定していない関数に対して、nullを渡すと怒られる。
強い。

以下のようなnullチェックがある関数だと怒られないらしい。
強い。

```js
/* @flow */

function length(x) {
  if (x !== null) {
    return x.length;
  } else {
    return 0;
  }
}

var total = length('Hello') + length(null);
```

TypeScript 1.4で導入予定のtype guardsに近い発想だ。
しかし、大きなbreaking changeになるのでTypeScriptには少なくともしばらくは入らんだろうなぁ。羨ましい。

## 型定義

普通にTypeScriptのlib.d.tsを参考にしてるっぽい
コンパイルエラーで表示されたメッセージから以下を拾うことができた。

```
This type is incompatible with
/**
 * Copyright (c) 2014, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the "flow" directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 */
/* JS primitives
   cf. http://typescript.codeplex.com/sourcecontrol/latest#typings/lib.d.ts
*/
```

## 配列

`Array<number>`形式しか受け付けないのかなと思って以下を試したけど普通にチェック通った。

```js
/* @flow */
function foo(x: number[]) {
  return x.reduce((p, c) => c + p, 0);
}
```

## union types

ふつーにある

## 弱くチェックするモード

```js
/* @flow weak */
```

## 型定義ファイルの使い方

[コマンドラインオプションで頑張る](http://flowtype.org/docs/third-party.html#interface-files)
多分 .flowconfig に書いてもイケる。

## コンパイルの仕方

[react-toolsで型注釈機械的に取り除くだけ？](http://flowtype.org/docs/running.html#_)
default valueにも対応してるようだけどうまく動かなくね？ブラウザ側が対応すれば使えるみたいなTypeScript以上のストロングスタイルなのかまさか。

## そもそも型定義ファイルいるの？

[なくてもパワーでわっしょいできそう](http://flowtype.org/docs/troubleshooting.html#required-module-not-found)

## Flowの処理系使ったら既存JSから雑な型定義ファイル生成できそうじゃね？

オナシャス！

## TypeScriptとの互換性

今んとこ割りとありそうに見える。
[mixedの導入](http://flowtype.org/docs/base-types.html) とか、微妙にTypeScriptにないものがあるような気もする。
Flow is superset of TypeScript 感。

## tupleがサポートされている

TypeScriptと同じ感じっぽいけどTypeScriptより頭悪い

```js
/* @flow */
var tup = ["1", 1, 2, "positive"];
tup.unshift(1);
console.log(tup[1] * tup[2]); // unshiftしたので 1st * 2nd は number * string だ！
```

これがエラーチェックをすり抜ける。
TypeScriptの場合、明示的にtupleと型注釈を与えない限りtupleにならないので、(string | number)[] となる。

## nullable の導入

[ここ](http://flowtype.org/docs/nullable-types.html#type-annotating-null)より

```js
/* @flow */
var o: ?string = null;
print(o.length);
```

良さそう…？な気もする？

## intersection types

[ここ](http://flowtype.org/docs/union-intersection-types.html)

うーん、これunion typesで表現可能な範囲だし、言語設計者が単に入れたかったら入れた感あるな…。

## dynamic type tests

[ここ](http://flowtype.org/docs/dynamic-type-tests.html)
TypeScriptがtype guardsと呼んでいるものをdynamic type testsと呼んでいるっぽい気がする。

## 生JSに型注釈版のサジェストをくれる

```js
/* @flow */
function foo(x) {
  return x.reduce((p, c) => p + c.charAt(0), "");
}

foo(["JavaScript", "TypeScript"]);
```

```diff
$ flow suggest hello.js
/private/tmp/flow/hello.js
--- old
+++ new
@@ -1,6 +1,6 @@
 /* @flow */
-function foo(x) {
-  return x.reduce((p, c) => p + c.charAt(0), "");
+function foo(x: Array<string>) : string{
+  return x.reduce((p: string, c: string) => : stringp + c.charAt(0), "");
 }

 foo(["JavaScript", "TypeScript"]);
```

…強い！！
神機能じゃね？arrow function expressionあたりがちょっとバグってるけど。

## 第二のインストール方法

```
$ brew install opam
$ opam init
$ eval `opam config env`
$ opam install flowtype
$ which flow
/Users/vvakame/.opam/system/bin/flow
```

## 総評

アンダース・ヘルスバーグ御大の設計は繊細で強いなと思った。
御大だったら入れてないだろコレ…みたいな感想をなんかテキトーに2〜3回くらい思った気がする。