TL;DR
- TypeScript のパフォーマンスの問題には、ビルド(
tsc)のものと言語サービス(tsserver)のものがある。 - ビルド時の型チェックを省く、不要なコードやパッケージを消す、インクリメンタルビルドとプロジェクト参照を使う、重い型を見直す、の 4 つで改善できる。
内容
ビルド時に型チェックをしない
TypeScript は、バンドラ(ts-loader を使った webpack や Vite)や ts-node など、他のツールを経由して実行されることが多い。このうち、Vite はデフォルトでトランスパイルだけを行うが、webpack(ts-loader)や ts-node は型チェックも行う。これを無効にするにはオプションを指定する(ts-node、ts-loader)。
デッドコードや不要なパッケージを削除する
noUnusedLocals を有効にすると、使われていないコードや型を検出できる。ただし、export されているのに使われていないシンボルは検出できないので、Knip のようなツールが必要になる。Knip は使っていないパッケージも検出できる。
プロジェクトに含まれるファイルの量を確かめるには、次のコマンドが使える。1 つ目はプロジェクトに含まれるすべてのソースを表示し、2 つ目はコンパイルされる各ファイルのバイト数を可視化する。
npx tsc --listFiles
npx tsc --noEmit --listFiles | xargs stat -f "%z %N" | npx webtreemap-cliインクリメンタルビルドとプロジェクト参照を使う
incremental を有効にすると、初回のビルドで作業の一部を .tsbuildinfo ファイルに書き出す。2 回目以降のビルドではこのファイルを読み込むので、速くビルドできる。プロジェクト参照と組み合わせると、さらに最適化できる。
型を見直す
型の書き方もコンパイラの速さに影響する。
-
大きなユニオン型を避ける。たとえば次の
Yearは 1000 個のメンバーを持つtype Digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" type Year = `2${Digit}${Digit}${Digit}` -
typeのインターセクション(&)ではなく、interfaceのextendsを使う(項目13) -
末尾再帰でない再帰的なジェネリック型を避ける(項目57)