巨大なコードベースを鎮圧する:tsconfig.json `extends` のその先にある「型安全の要塞」
TypeScriptのプロジェクトが成長し、数万行を超えたあたりで、多くのエンジニアが直面する壁がある。「設定ファイルのスパゲッティ化」だ。特にモノレポやマイクロフロントエンドの構成では、個別のパッケージごとに `tsconfig.json` をコピペして管理するのは、自らバグの温床を耕しているようなものだ。
今日は、ただの「設定の共通化」を超え、型安全の要塞を築くための `extends` 戦略について語ろう。
—
なぜ `extends` は単なる「DRY」以上の意味を持つのか
多くの開発者は、`extends` を「設定の重複を避けるためのツール」としか捉えていない。しかし、アーキテクトの視点で見れば、これは「プロジェクト全体の型安全性のベースラインを強制するガバナンス機構」だ。
例えば、`strict: true` を各所に散らばせる運用は、いつか誰かが「特定のモジュールだけ緩めたい」という誘惑に負け、プロジェクト全体の整合性を崩す引き金になる。基盤となる設定を抽象化し、末端に継承させることで、「堅牢性という名の規律」を物理的に強制できる。
階層化されたコンフィグ戦略
以下のように `tsconfig.base.json` を頂点とした階層構造を推奨する。
// tsconfig.base.json – プロジェクト全体の「憲法」
{
“compilerOptions”: {
“target”: “ESNext”,
“module”: “NodeNext”,
“strict”: true, // 妥協なき型安全の強制
“esModuleInterop”: true,
“skipLibCheck”: true, // パフォーマンス向上の要。型チェックをライブラリ定義まで広げるとビルドが死ぬ
“forceConsistentCasingInFileNames”: true,
“moduleResolution”: “NodeNext”
}
}
パフォーマンスと型計算の最適化:`extends` でやるべきこと
`tsconfig.json` の設定ミスは、単にビルドエラーを出すだけでなく、TypeScriptの型推論エンジン(TSServer)のメモリ消費量を爆増させる原因になる。
特に大規模プロジェクトで注意すべきは、`include` と `exclude` の設計だ。`extends` を活用して、実行環境ごとに必要最小限のファイルをコンパイル対象に絞り込むことで、LSP(Language Server Protocol)のインデックス作成時間を劇的に短縮できる。
実践的な「環境別継承」の構成例
// tsconfig.app.json – ブラウザ向けアプリケーションの設定
{
“extends”: “./tsconfig.base.json”,
“compilerOptions”: {
“lib”: [“DOM”, “DOM.Iterable”, “ESNext”],
“jsx”: “react-jsx”
},
“include”: [“src”],
“exclude”: [“node_modules”, “dist”, “/.spec.ts”] // テストファイルを除外してインデックス負荷を下げる
}
ここで重要なのは、「テストファイルやビルド成果物を除外する」ことだ。型チェックのたびに巨大なテストコードまで解析させていると、エディタでの補完が数秒遅れる「死のラグ」を体験することになる。
—
避けるべき「重大なバグ」とアーキテクチャの陥阱
現場でよく見る悲劇は、`paths` マッピングの不適切な継承だ。
// 悪い例:継承先でpathsを再定義してしまい、解決順序が崩壊する
{
“extends”: “./tsconfig.base.json”,
“compilerOptions”: {
“paths”: {
“@/”: [“./src/”] // 親の設定と衝突し、モジュール解決の競合を招く
}
}
}
`paths` を `extends` する際、親の設定を上書きしてしまうと、`tsc` はモジュールを探すために無駄なパス探索を行う。これは単なるバグだけでなく、「ビルド環境では動くが、開発環境では型が当たらない」という、最も解決に時間を浪費する類の問題を引き起こす。
アーキテクトとしての助言: `paths` はプロジェクトのルート(`base`)で一元管理し、個別のパッケージでは `references`(Project References)を使用して、ビルドグラフを明示的に分離せよ。
—
結論:型安全は「規律」から生まれる
TypeScriptにおいて、`tsconfig.json` は単なる設定ファイルではない。それはチームのエンジニアがどのようなコードを書くべきかという「意思表示」であり、コンパイラに対する「命令」そのものだ。
1. `skipLibCheck: true` でビルド時間を守れ。
2. `include/exclude` を精緻に制御し、LSPのメモリ使用量を最適化せよ。
3. `extends` を使って、プロジェクト全体の型安全性を「憲法」として強制せよ。
コードベースが巨大になればなるほど、ツールに依存するのではなく、ツールを制する「構成力」が問われる。君たちが今日書いたその `tsconfig.json` が、未来の自分たちの開発体験(DX)を決定づけるのだ。さあ、今すぐ設定を整理し、無駄のない強固なビルドパイプラインを構築してほしい。
健闘を祈る。

コメント