JavaScriptで厳格な型チェックを行なうライブラリを書いた
先日のjava-ja温泉で「JavaScriptは独りでヒャッハーするのには良いけど、複数人で開発しだすと途端にカオスになって苦労する」という話になった。それに対する解の一つはClosure Compilerが採用したアノテーションによる型の定義と静的チェックだろう。それとは別のアプローチで何かできないかなと考えていたら、ECMAScript 6にObjectのプロパティアクセスをフックできる仕組み(Proxy.create)があったのを思い出した。Proxy APIを使ってみたら型チェックが効くC言語の構造体みたいな物が作れたのでライブラリ化した。
これを使うと何が良いかというと
obj = {}; obj.hogeFuga = new Foo(); // do something obj.hoge_fuga = null; // 不要になったので解放 (タイプミス)
といった、動かしてもすぐには気づきにくいミスに例外を投げてくれる。Object.seal でも良いけど、未定義プロパティのreadに対しては何もしてくれないのが不満だったので、それも例外が飛ぶようにした。
使い方は次の通り。Object.defineProperties に似せた。
// 構造体の定義 Struct.define('Position', { x: {type: 'number'}, y: {type: 'number'} }); Struct.define('Square', { name: {type: 'string', writable: false}, pos: {type: 'struct:Position'}, hidden: {type: 'boolean'} }); // 作成 var sq = Struct.create('Square', { name: 'mySquare', hidden: true }); // 通常のObjectと同様に扱える sq.pos = Struct.create('Position', {x: 10, y: 20}); sq.hidden = false; console.log(sq.name); // => mySquare console.log(sq.pos.x); // => 10 // 以降の操作は全てチェックエラー var name = sq.Name; // 未定義プロパティの読み取り delete sq.Name; // 未定義プロパティのdelete sq.visible = true; // プロパティの追加 sq.pos.x = "100"; // 型の不一致 sq.name = "hoge"; // 読み取り専用プロパティの変更
動作にはECMAScript 6 のProxyが必要なので、Firefox or 設定をいじったChromeじゃないと動かない。しかしProxyが無くても例外が飛ばないだけなので問題は無い、開発時にエラーが飛んでくれればそれで良いと考えているので。
(追記) ChromeでProxyを有効にする方法を書きました。