Parcel で TypeScript を使うのを諦めた話#
結論から#
- 公式で TypeScript サポートと書かれている。
- しかし、ビルド時に型チェックされなく、構文エラーすら通す状態である。
- その点を直す良さそうな方法が見つからなかったので、TypeScript で書きたいなら Parcel は使わない方が良いと判断した。
後日 04-15 追記#
と、上記の結論のように考えていたが、Twitter や会社のチャットでツッコミをもらい、 Parcel 側の責ではなく、自分の考えていたローカル開発環境の常識が古いことに原因がありそうだった。
具体的には、自分は以下のようにローカル開発環境かくあるべしと考えていたが、
-
適宜
tsc
を実行すれば、意図した書式の .ts が担保できるのはわかる。 例えば、リポジトリが保守すべき基準として CI ではそれを実行するのだろう、という点は想像できる。 - ただし、それを parcel の watch と同期できなければ、 ローカル開発中にファイル更新毎に実行することはできず、著しく不便である。
おそらく Parcel を含む最近のフロントエンド JavaScript 界のトレンドでは、 ファイル更新と同期したコード検証は、エディタなどの機能を使い開発者個人の責任で担保する、 ということになっていそうだった。
つまり今回のケースでいうと、VSCode とかで検証環境を作ってない自分の筋が悪いという話である。
いわれてみるとだが、個人の開発効率を担保するためのコードをリポジトリに入れるよりは、各人に任せた方が正しそうである。
特に、ファイルディスクリプタに依存するような機能は各人の環境で固有の問題が出やすく、 プロジェクト単位でメンテナンスするにはやや非効率という側面がある。
また、そういった「ファイル更新毎に自動実行」という機能を欲してない人もいる。 例えば、発見してしまった Typo 修正を投げるだけのゲストなら不要だろうし、 そもそも「自動実行が嫌い」という嗜好を持つ人もいるだろう(個人的に理解はできる)。
型チェックされず、構文エラーも通す状態の例#
package.json
から一部抜粋)
"devDependencies": {
"parcel-bundler": "^1.12.3",
"typescript": "^3.4.3"
}
tsconfig.json
)
{
"compilerOptions": {
/* Basic Options */
"jsx": "react",
"lib": [
"dom",
"es2018"
],
"module": "commonjs",
"moduleResolution": "node",
"newLine": "lf",
"target": "es5",
/* Strict Type-Checking Options */
"strict": true,
/* Additional Checks */
"noFallthroughCasesInSwitch": true,
"noImplicitReturns": true
}
}
src/index.html
)
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>tower-offense-7x7</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div class="js-app"></div>
<script src="./index.ts"></script>
</body>
</html>
src/index.ts
)
// 型が正しくない
let a: number = 1;
a = 'abc';
// const へ再代入
const b = 1;
b = 2;
// 構文エラー
const c: = 1;
console.log('Hello, index.ts!');
上記を用意して、parcel build
を実行する。
./node_modules/.bin/parcel build --no-cache --no-minify src/index.ts
結果、exit status は 0 を返し、生成物である dist/index.js の src/index.ts 相当部分を確認すると、以下のようになっている。
})({"7QCb":[function(require,module,exports) {
"use strict"; // 型が正しくない
var a = 1;
a = 'abc'; // const へ再代入
var b = 1;
b = 2; // 構文エラー
var c = 1;
console.log('Hello, index.ts!');
},{}]},{},["7QCb"], null)
なぜそうなるのか#
ローカルの node_modules/parcel-bundler へデバッグプリントを入れつつ確認したところ、.ts のコンパイルは以下に抜粋で引用する この行 の typescript.transpileModule
で行なっていた。
// Transpile Module using TypeScript and parse result as ast format through babylon
let transpiled = typescript.transpileModule(
this.contents,
transpilerOptions
);
そして、この transpileModule
で各種エラーのチェックをしたい場合は、渡すオプションが足りない。
例えば、構文エラーを判別したかったら reportDiagnostics: true というオプションが必要だし、 型チェックなどをさせたかったらより多くのオプションが必要になるらしい。
transpileModule
の仕様はちゃんと追ってないのだが、とりあえず Parcel 側はここでの型チェックは現状やってなさそう、という推測をした。
なお、tsconfig.json の設定は正しく渡されていた。
公式に頼らない解決方法#
- fathyb/parcel-plugin-typescript を使う。
- 10 months 更新がないので厳しそう。
- tsc コマンドを適宜呼び出す。
- この点は、parcel 側の watch フックをカスタマイズする方法がわからなかったので保留にした。
- ただこの時点で、そこまでして Parcel 使わないでもいいやって思ったので Game Over である。