flowtype v0.32.0 changes

flowtype v0.32.0がリリースされました

Release v0.32.0 · facebook/flow · GitHub

この変更では待望のgen-flow-filesコマンドが追加されています。 これはflowtypeのシンタックスで書いたjsファイルから、型定義情報を生成するコマンドです。

これまではライブラリ作者が型定義情報を提供しようとした時に、外部提供用の.js.flowを別途用意する必要がありましたが、これによってその必要がなくなります。 まだalpha-levelなので、安心して使うにはもう少し待つ必要がありそうですが、これは非常に捗りますね。

その他何点か機能追加があったので試してみます。

gen-flow-files コマンドの追加

先ほども書きましたが、待望の機能です。 flowtypeのシンタックスで書いたjsファイルから、型定義情報を生成することができます。

  • calcRectArea.js
// @flow

type Rect = { x: number, y: number };
export default function calcArea(rect: Rect) {
  return rect.x * rect.y;
}

このjsファイルに対して、flow gen-flow-files [filename] を実行します。

$ flow gen-flow-files calcRectArea.js
// @flow

declare export default function(rect: {x: number, y: number}): number;

declare export default function(rect: {x: number, y: number}): number; という型定義情報が出力がされてますね。

便利。

exact object types シンタックスの追加

これまでflowにおいて、オブジェクトの型定義は{ hoge: type}のみでしたが、より正確なオブジェクトを定義するためのシンタックスとして{| hoge: type |}が追加されました。

{ hoge: string}と記述した場合には、「少なくともstring型であるhogeプロパティが含まれること」という検証がされます。 {hoge: 'hoge', bar: 'bar'}というオブジェクトは、この型定義に当てはめた時にbarが余計に含まれていますが、上記の条件は満たしているため検証が通ります。

{| hoge: string |}と記述した場合には、「string型であるhogeプロパティのみを持つこと」という検証がされます。 {hoge: 'hoge', bar: 'bar'}というオブジェクトは、barプロパティを余計に持ってしまっているためエラーとなります。

従来の型定義

// @flow

type Rect = { x: number, y: number };
function calcArea(rect: Rect) {
  return rect.x * rect.y;
}

console.log(calcArea({ x: 2, y: 3, z: 4 }));
$ flow
No errors!

exact object types

// @flow

type Rect = {| x: number, y: number |};
function calcArea(rect: Rect) {
  return rect.x * rect.y;
}

console.log(calcArea({ x: 2, y: 3, z: 4 }));
$ flow
exact.js:8
  8: console.log(calcArea({ x: 2, y: 3, z: 4 }));
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function call
  8: console.log(calcArea({ x: 2, y: 3, z: 4 }));
                          ^^^^^^^^^^^^^^^^^^^^ property `z`. Property not found in
  3: type Rect = {| x: number, y: number |};
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^ object type


Found 1 error

resource filesのデフォルト型定義情報の追加

.css, .jpg, .png, .gif, .eot, .svg, .ttf, .woff, .woff2, .mp4, .webm のファイルをrequireしたときにデフォルトで型定義情報が付与されるようになりました。 .cssはObjectとなり、他のリソースファイルはstringとなります。

(this list is not configurable at the moment).

だそうなので、そのうち設定ができるようになりそうです。

自分で型定義を与えたい場合には、これまでどおりmodule.name_mapperで設定する必要があります。

参考: Flow | Advanced Configuration

flowはtype-at-posコマンドで、指定した位置の変数の型定義を出力することができるので、これを使って試してみます。

  • requireResource.js
// @flow

import css from './test.css';
import gif from './test.gif';

console.log(css);
console.log(gif);
$ flow type-at-pos requireResource.js 6 13
Object
/Users/joe-re/src/try-flow-032/requireResource.js:6:13,6:15

See the following locations:
/Users/joe-re/src/try-flow-032/requireResource.js:6:13-15:
Flow assumes requiring a .css file returns an Object

6 13という引数は6行目の13列という指定です。css変数を指定しています。 想定どおりオブジェクトが返ってます。

[~/src/try-flow-032]$ flow type-at-pos requireResource.js 7 13
string
/Users/joe-re/src/try-flow-032/requireResource.js:7:13,7:15

See the following locations:
/Users/joe-re/src/try-flow-032/requireResource.js:7:13-15:
string

こちらはgif変数を指定しています。 こちらも想定どおりstringが返ってます。

WACULさんと共同で勉強会を開催しました #fr_wa_lt

f:id:joe-re:20160613002825p:plain

connpass.com

WACULさんと共同で勉強会を開催しました。

登壇者、来場者の方々ありがとうございました!

内容はとにかくLT大会という感じです。

LT

flowtypeによるコンポーネント指向における型の入手 by @joe_re

speakerdeck.com

flowtypeによるjsの世界における静的型付けの導入について。React + Reduxに適用する例など。

NSQについて by @tutuming

speakerdeck.com

bit.ly製の分散型MQサービスのNSQの紹介。シンプルで扱いやすく、スケーラビリティが高いところが魅了に感じた。

Rails+webpackの落ち穂拾い by @kuy

speakerdeck.com

Sprocketsから脱却した後の残作業についてのお話。 具体的にはi18n対応のための定義やimageのasset pathなどをRailsとフロントでどうやって共有するかなど。 そういう部分をWebpackのbuildに寄せてしまうのはありかもというお話もしていて、なるほどワンチャンありそうだと思った。

Reactテストに役立つ実装の工夫 by @teppei_tosa

http://www.slideshare.net/ironpeace/react-62928705?ref=http://connpass.com/event/31305/presentation/www.slideshare.net

Reactでのユニットテストを書く上での実践的なお話。テスト書く気持ちが高まった。

GraphQL with Angular2 by @Quramy

GraphQL with Angular2

RelayのReact依存を引き剥がしてAngular2で使うというお話。 RelayはReact専用に作られたもので、これからもそれは変わらないと思っていたのだけど、CoreAPIを切り出したいissueがあり、すでにexperimentalな実装もあるらしい。ほー。

Electron + WebDriver = Spectron by @Linda_pp

speakerdeck.com

ElectronのE2Eテスト用アプリケーションのSpectronについてのお話。デスクトップでE2Eテストできてしまうのすごい。

フロントエンドのモダン化とJavaScriptモジュールの
依存解決 by @_tohashi

speakerdeck.com

Railsアプリケーションにおいて、JS分割、ComonJSやES6-Modulesによる依存解決をどう推し進めていくかというお話。後半の「Webpack & Speockets 両対応」は良い泣きどころ。

WACULの解析基盤について by @ito_taro

WACULさんの解析基盤についての紹介と、理論(数学)的なお話。分かりやすいお話で面白かった。(高校の授業を思い出した。)

外部入力の改行に負けない体を作る by @yoshiko_pg

外部入力の改行に負けない体を作る - @yoshiko_pg

改行を表現することのできるcssプロパティ white-space: pre-line; のお話。もう改行には悩まない。

freee-wacul-web-app-lt-one(React Nativeについて) by @xga

speakerdeck.com

React Nativeについてのお話。Webの技術でNativeなアプリを書ける。

詳しくはご本人のブログで。 freee x WACUL Modern Web App LT #1 で React Nativeについて話しました - futoase

WebAssembly試してみた by @ukyo

WebAssembly試してみる

Web Assemblyのお話。wast思ったより普通に書けるって紹介されてて、確かに思ったより普通に書けそうだなーって思ったけど、やっぱりつらそうだった。wastで画像のぼかしフィルター処理を書いたデモを披露していてカッコよかった。

Front-end Server by @qsona

slides.com

Thin Server Architecture、Micro services化、BFFを構築する上でのフロントとサーバの境界線をどう考えるか、などについてのお話。
このお話中に、MicroserviceについてのMeetupをConnpassで公開されていました。興味がある方は是非!

microservices-meetup.connpass.com

飛び入りLT

@wadahiroさんと@nekoneneneさんが飛び入りでLTしてくださった。

@wadahiroさんは、今月行われたReact Europe2016についてのお話。
(↓でセッションの映像が観られます。)
www.youtube.com

@nekoneneneさんは、最近のニュースやtipsなどをまとめたお話をしてくださいました。

モダンWeb ミニミニLT.pdf - Google ドライブ

感謝

LT大会では @ymrl に司会をしてもらいました。

準備もWACULさんが早めに来てくれたり、弊社の有志メンバーが集まってやってくれたりしてすごく助かった。

当日手伝ってくれた方々ありがとうございました! 🙇🙇🙇

ちゃんと開催できたのはみなさんのおかげです。

感想

この勉強会は@Quramyさんと何かの勉強会で会った時に「共同で勉強会っぽいものやりませんか???」みたいな話をしてて、そのままの流れでシュッと開催された。

深く考えずに勢いで開催したのだけど、その割にはレベルも高い良い勉強会になったなーと思う。

低コストでハイパフォーマンスを出せることは尊い。またやりたい。

flowtypeの実現する実行時例外のない世界

今日こんなスライドを見かけた。

djcordhose.github.io

これはtypescriptとflowtypeの違いがよく分かるすごく良いスライド。

このスライドの5ページ目に以下の1文がある。

FLOW SOUNDNESS, NO RUNTIME EXCEPTIONS AS GOAL

スライドに刺激を受けたのと、最近flowtypeを触っていたのもあって、これが何を指しているか書きたくなった。

実行環境

  • flow: 0.26.0
  • typescript: 1.18.10

Flowtypeのきほん

以下のjavasciptのプログラムをflowにかけてみる。

function foo(x) {
  return x * 10;
}
foo('Hello, world!');
$ flow
flow.js:5
  5: foo('Hello, world!');
     ^^^^^^^^^^^^^^^^^^^^ function call
  3:   return x * 10;
              ^ string. This type is incompatible with
  3:   return x * 10;
              ^^^^^^ number

関数fooは引数xに対して10を掛けた値を返却する。
引数xにはnumber型を期待しているが、実際にはstringを渡しているのでエラーが発生する。

非常に強力な型推論だ。

ちなみにtypescriptではこれはエラーにならない。
(まぁjsのシンタックス上エラーじゃないし)

$ node
> null * 10
0

typescriptにおいては以下のように引数xの型を明示的に指定することでこれを検知できる。

function foo(x: number) {
  return x * 10;
}
foo('Hello, world!');

これをOCamlで記述してみる。

let foo x = x * 10;;
# val foo : int -> int = <fun>

let foo x = x * 10;;の評価値がval foo : int -> int = <fun> である。
fooはintを受け取ってintを返す関数である、という評価がされた。
OCamlにおいてもxはint型だと推論されていて、flowtypeはOCaml製だけあって近い挙動を示す。

nullable typeを定義

関数fooに少し手を加えて関数barを定義する。

function bar(x) {
  if(x < 10) { return null; }
  return x * 10;
}

console.log(bar(1) * 10);

関数barは、引数が10以下である時にnullを返す。
これをflowtypeにかけてみる。

$ flow
flow.js:8
  8: console.log(a * 10);
                 ^ null. This type is incompatible with
  8: console.log(a * 10);
                 ^^^^^^ number

barはnullを返す可能性があるが、そのハンドリングをせずに * 10しているため、エラーとなる。
ここでは関数barはnullableなnumberを返す関数となったことになる。

ここでnullのチェックを入れると、このエラーは解消される。

function bar(x) {
  if(x < 10) { return null; }
  return x * 10;
}

const a = bar(1);
if (a) {
  console.log(a * 10);
}
$ flow
No errors!

この世界において、runtime exceptionが起きる可能性がまた1つ根絶された。
これが冒頭の NO RUNTIME EXCEPTIONS AS GOAL を端的に表した例だ。

これもOCamlで記述してみると、以下になる。

let bar x =
  if x < 10 then None
            else Some(x * 10);;
# val bar : int -> int option = <fun>

int optionOCamlの提供するOptionという型で、int型かもしくは値がない、ということを示している。
この挙動を知っていれば、先ほどの結果にも素直に頷ける。

スライドにも出てくるけど、typescriptも2.0でNon-nullable typeに対応するらしい。期待。
https://github.com/Microsoft/TypeScript/pull/7140

もうマージはされていて、最新repositoryで strictNullCheckstarget es6 を有効にすれば動くらしい。
今度試してみよう。