2016-06-24 TypeScript + Babel するなら --module commonjs すべき
豪旅行の 1 日目だけど、CommonJS Interop の話を書く。
ここ数日 ES Modules と CommonJS の対応について調べていた。TypeScript と Babel および Node.js の 3 つだ。Node.js はまだ案の段階だ。現在の案は Babel に近づけている。
結論から言うと、TypeScript と Babel を併用する場合は --module commonjs
にしておくと良い。ぼくの主観では TypeScript が好みなのだけど、Babel の user 数を理由に Node.js 案は Babel 寄りになりそうだ。確定ではない。TypeScript の --module es2015
とそれ以外は解釈に矛盾があるので Babel / Node.js 案との併用時に使用すべきでない。解釈の良し悪しを議論したのかは知らないが、多数決で不適切な選択がされているような印象を受けており、Babel を使うと死ぬ病気が流行ればいいのにと思っている。ちなみにぼくは併用しているので死ぬ側の人間だ。
改めて。
TypeScript と Babel の大きな違いは module.exports
を ES Modules における export の ns として扱うか ns.default として扱うかだ。
解釈 1 TypeScript 。つまり module.exports
を ns として扱う場合、 cjs だと ns を破壊できることになる。たとえば module.exports = 123;
などができる。これは import v from 'mod';
できないし、import * as ns from 'mod';
すると ns が object にならない点でおかしい。逆に言うと ns を破壊できるだけなので module.exports = 123;
を import * as ns from 'mod';
すると ns === 123
になるだけのことだ。
Babel 。つまり module.exports.default
を ns として扱う場合、さらに 2 つの派生系がある。module.exports.foo
を ns.default.foo として扱うか、ns.foo として扱うかだ。Babel や Node.js 案は後者だ。
解釈 2 前者の場合、つまり module.exports.default
を ns として扱い、module.exports.foo
を ns.default.foo として扱う場合は、破壊を避けられ、一貫性がある。しかし、import {x} from 'mod';
のような名前付きの import の一切が機能しない。import v from 'mod'; const { x } = v;
などと ns.default からの取り出しが必要だ。
解釈 3 後者の場合、つまり module.exports.default
を ns として扱い、module.exports.foo
を ns.foo として扱う場合は、破壊を避けられるが、一貫性がない。import * as ns from 'mod';
は module.exports
を ns として扱う default 以外の場合とそうでない場合がある。
ぼくは TypeScript の解釈 1 が好きだ。2 は理想的だが対応している実装はない。module.exports
を default
とそれ以外の両方で使うという判断は、変換規則をいびつにしていると思う。
ただし、冒頭に書いたとおり Node.js の案の方向は解釈 3 だ。
個人的には数の暴力を受けている印象を受けており不愉快だけど、現実問題として Babel やその user を皆殺しにできるわけでもないので、ぼくのほうで回避するしかない。
TypeScript 側の回避策としては TypeScript の cjs interop は他と違うことを自覚して、変換される形を意識しながら利用することだ。つまり TypeScript を cjs と組み合わせる場合は --module commonjs
して使う。--module es2015
したものが Babel / Node.js 案で解釈されると、default export/import で予期しない動作になるからだ。
これは Node.js の議論がどこに落ち着くかに関わらず、現時点の TypeScript + Babel 環境でも言える。TypeScript と Babel を併用する場合は --module commonjs
にしておくと良い。2016-03-15 や 2016-06-20 を踏まえた、ぼくの中での結論だ。
Node.js の開発者たちに少数派だから死んでもいいと見なされている TypeScript user の参考になれば幸いだ。