Parcel で TypeScript を使うのを諦めた話#

結論から#

後日 04-15 追記#

と、上記の結論のように考えていたが、Twitter や会社のチャットでツッコミをもらい、 Parcel 側の責ではなく、自分の考えていたローカル開発環境の常識が古いことに原因がありそうだった。

具体的には、自分は以下のようにローカル開発環境かくあるべしと考えていたが、

おそらく 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 の設定は正しく渡されていた。

公式に頼らない解決方法#