なぜ「なんとなく」でtsconfigのlibを放置するのか?――TypeScriptの型定義を制御して、開発体験を劇的に変える話
現場でコードを書いていると、たまにこういう光景を目にする。「とりあえず `tsconfig.json` の `lib` はデフォルトのまま放置」あるいは「エラーが出るからとりあえず全部詰め込んでおく」というやつだ。
これ、実はかなりもったいないことをしている。`lib` プロパティは、単なる「型定義の読み込み設定」ではない。そのプロジェクトが「どの環境で生きるか」を定義する、いわばフロントエンド・アーキテクトとしての最初の意思表示なんだ。
今日は、中級者の壁を越えるために、`lib` プロパティをどう制御し、なぜそうすべきなのか、現場のリアルな視点から解説する。
—
1. libプロパティが裏側でやっている「残酷な真実」
TypeScriptの `lib` 設定は、JavaScriptの組み込みオブジェクト(`window`, `document`, `Array`, `Promise` など)の型定義ファイルを読み込むためのスイッチだ。
もし `lib` を指定しないと、TypeScriptはコンパイルターゲット(`target`)に合わせて自動的に `lib` を推論する。しかし、現代の複雑なフロントエンド開発において、この「自動推論」を信じ切るのはリスクが高い。
例えば、ReactでWebアプリを作っているのに、意図せず `WebWorker` の型が入り込んでいたらどうなるか? `self` を参照したときにWorkerの型定義が優先され、思わぬ型エラーや補完の汚染を招く可能性がある。「必要なものだけを、必要なだけ読み込む」。これが、堅牢な型システムを構築する第一歩だ。
—
2. 実践:環境ごとのベストプラクティス
現場でよくある構成をパターン別に整理した。これをベースに、自分のプロジェクトに合わせて調整してみてほしい。
パターンA:一般的なWebアプリケーション(ブラウザ用)
これが最も標準的な設定だ。ESの最新機能とDOM操作、そしてDOMのイベント操作を許可する。
{
“compilerOptions”: {
“target”: “ESNext”,
// DOM操作、ES2022までの機能、Promise関連の型定義を有効化
“lib”: [“DOM”, “DOM.Iterable”, “ESNext”]
}
}
- DOM: `document` や `window` などのブラウザAPI
- DOM.Iterable: `NodeList` などを `for…of` で回すために必須
- ESNext: 最新のJavaScript構文の型定義
パターンB:WebWorker専用のロジックを切り出す場合
メインスレッドとWorkerを同じプロジェクトで管理しているなら、`tsconfig` を分離するのが正解だ。
{
“compilerOptions”: {
“target”: “ESNext”,
// DOM(ブラウザ画面)を除外し、Workerのグローバルスコープを定義
“lib”: [“WebWorker”, “ESNext”]
}
}
- WebWorker: `DedicatedWorkerGlobalScope` 等の型が使えるようになる。
- この設定にしておけば、間違えて `window` を叩こうとした瞬間にコンパイルエラーが出る。これが「型による安全設計」の醍醐味だ。
—
3. なぜ「絞り込む」ことが重要なのか?
中級エンジニアが意識すべきは、「汚染の防止」だ。
例えば、`lib` に `DOM` を入れたままにしておくと、Node.jsで動くサーバーサイドのコードを同じリポジトリで書いているとき、意図せずブラウザ専用のAPI(`alert()` や `fetch()` など)が補完に出てきてしまう。
これが発生すると、「Node.js上で動かしているはずなのに、なぜかブラウザのAPIが使えてしまう」というデバッグ困難なバグを生む温床になる。
- フロントエンドのアプリ: `DOM` を含む
- バックエンド/ツール系: `DOM` を除外する(`ESNext` のみなど)
このように、`lib` を明確に分けるだけで、コードの「コンテキストの混濁」を物理的に防ぐことができる。
—
4. チーフアーキテクトからのアドバイス
最後に、実務で役立つTipsを一つ。
もし将来的に「Node.jsとブラウザの共通パッケージ」を作ることになったら、`lib` を極限まで絞り込んでみてほしい。ブラウザ特有のAPIを一切含まない `lib` 設定でコンパイルを通すように意識すれば、そのコードは驚くほど移植性が高く、堅牢なものになる。
「tsconfigは、そのプロジェクトの『境界線』を引くための地図である」
そう考えて設定を見直してみると、今まで見えていなかった依存関係や、本来あるべきコードの分離の仕方が見えてくるはずだ。
設定ファイルは単なるおまじないではない。君のチームの技術力を担保する「最初の防波堤」だと思って、ぜひ今日の帰り際にでも、プロジェクトの `lib` 設定を眺めてみてほしい。きっと、いくつか「不要なもの」が見つかるはずだよ。

コメント