tsc vs esbuild:型チェック vs 高速なトランスパイル
両者は役割が異なります。esbuild は TypeScript を極めて高速にトランスパイルしますが型チェックをスキップします。tsc は型チェックを行い(出力も可能)ますが低速です。
よくある混同:esbuild は型を検証せずに除去して TS を JS にコンパイルするため、型エラーを一切報告しません。tsc は実際に型をチェックします。多くのチームは build に esbuild(または swc)を、型チェックに tsc を使います。
| tsc | esbuild | |
|---|---|---|
| 型チェック | あり(本来の目的) | なし(型を除去するのみ) |
| トランスパイル速度 | 低速 | 非常に高速 |
| 出力/バンドル | 出力あり、バンドルなし | トランスパイル + バンドル |
| 型エラーの報告 | あり | なし |
| 典型的な役割 | 型ゲート | build/transpile ステップ |
通常なぜ両方が必要か
esbuild は実行可能な JS を高速に生成しますが、型システムを理解しないため、実際の型エラーが紛れ込んだまま build が成功してしまうことがあります。tsc は型が誤っているときに失敗する唯一のツールです。esbuild だけを使うと、型安全というセーフティネットを失うことになります。
一般的な構成
速度のために esbuild(または swc)で build/bundle し、別ステップとして tsc --noEmit を実行して型チェックします。これにより高速な build と本物の型検証の両方が得られます。ローカルの watch モードでは速度のために esbuild を使い、CI では正しさを強制するために tsc を実行します。
CI では
tsc --noEmit を独立した job/ゲートとして実行し、高速な esbuild の build が型のリグレッションを隠さないようにします。esbuild は build ステップを高速に保ち、tsc は型を正直に保ちます。両者は競合するのではなく補完し合います。
結論
どちらか一方を選ぶのではなく、高速なトランスパイル/バンドルには esbuild(または swc)を、型チェックには tsc --noEmit を使いましょう。esbuild だけでは型エラーを検出できず、tsc だけでは build が遅くなります。