TypeScriptを用いた開発において、プロジェクトの肥大化に伴いコンパイル対象の管理は非常に重要な課題となります。
設定ファイルである tsconfig.json の中で、どのファイルをコンパイルに含めるか、あるいは除外するかを制御するのが include と exclude の役割です。
これら二つのプロパティを正しく理解し使い分けることは、ビルド時間の短縮や意図しない型エラーの防止に直結します。
本記事では、2026年現在のモダンな開発環境を踏まえ、include と exclude の決定的な違いと、それらが適用される優先順位について詳しく解説します。
includeプロパティの役割と基本的な使い方
include プロパティは、TypeScriptコンパイラがプログラムの一部として扱うべきファイルやディレクトリを指定するために使用されます。
このプロパティを指定しない場合、デフォルトでは tsconfig.json が存在するディレクトリ以下のすべての .ts、.tsx、.d.ts ファイルが対象となります。
明示的に include を記述することで、コンパイル対象を特定のディレクトリに限定することが可能になります。
ワイルドカード(Globパターン)の利用
include では、ファイルパスを直接記述するだけでなく、Globパターンと呼ばれるワイルドカードを利用できます。
代表的なパターンには以下の3種類があります。
*:0文字以上の文字(ディレクトリ区切りを除く)に一致します。?:任意の1文字(ディレクトリ区切りを除く)に一致します。**:任意のレベルのサブディレクトリに一致します。
例えば、src ディレクトリ配下のすべてのファイルを対象にする場合は、以下のように記述します。
{
"compilerOptions": {
"outDir": "./dist",
"rootDir": "./src"
},
"include": [
"src/**/*" // srcディレクトリ内のすべてのファイルを対象にする
]
}
includeを指定した際の注意点
include を使用する場合、指定したパターンに一致しないファイルはコンパイル対象から外されます。
しかし、後述する「import文による参照」がある場合は、この限りではありません。
また、include はあくまで「コンパイルを開始する入り口」を定義するものだと理解しておく必要があります。
excludeプロパティの役割と仕組み
exclude プロパティは、include で指定されたファイル群の中から、特定のファイルやディレクトリをコンパイル対象から除外するために使用します。
よくある誤解として、「exclude に書けばそのファイルは絶対に読み込まれない」というものがありますが、これは正確ではありません。
exclude はあくまで include の結果に対するフィルタリング機能として働きます。
デフォルトで除外されるディレクトリ
exclude プロパティを明示的に指定しない場合、TypeScriptはデフォルトで以下のディレクトリを除外します。
node_modulesbower_componentsjspm_packagesoutDirで指定された出力ディレクトリ
もし exclude を自分で定義した場合、これらのデフォルト設定は上書きされるため、必要に応じて node_modules などを再度明示的に追加する必要があります。
{
"compilerOptions": {
"outDir": "./dist"
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"src/**/*.spec.ts", // テストファイルを除外する
"dist"
]
}
excludeが適用されるタイミング
TypeScriptコンパイラは、まず include に基づいてファイルのリストを作成します。
その後、そのリストから exclude に一致するファイルを取り除きます。
このため、includeに含まれていないファイルに対してexcludeを指定しても意味がありません。
includeとexcludeの優先順位と「インポートの罠」
include と exclude の関係性において、最も注意すべきなのは「ファイル間の依存関係」です。
これには明確な優先順位のルールが存在します。
import文による強制的な取り込み
これが最も重要なポイントですが、excludeで除外したファイルであっても、他のコンパイル対象ファイルから import されている場合は、コンパイルに含まれてしまいます。
TypeScriptは型安全性を担保するために、プログラムが依存しているすべてのファイルの型情報を必要とするからです。
例えば、src/main.ts が src/test-helper.ts をインポートしている場合、exclude に src/test-helper.ts を指定しても効果はありません。
これを完全に防ぐには、コード内での import 自体を解消するか、プロジェクトを適切に分割する必要があります。
filesプロパティとの関係
tsconfig.json には、include の他にも files というプロパティが存在します。
files はファイルパスを1つずつ正確に指定する方式で、Globパターンは使えません。
重要なのは、filesで指定されたファイルは exclude の設定を無視して必ずコンパイル対象になるという点です。
優先順位を整理すると、以下のようになります。
| プロパティ | 優先度 | 特徴 |
|---|---|---|
| files | 最高 | 個別に指定。excludeの影響を受けない。 |
| exclude | 中 | includeの結果からファイルを除外する。 |
| include | 低 | ワイルドカードで範囲を指定する。 |
実戦的な使い分けのパターン
プロジェクトの構成に応じて、include と exclude をどのように組み合わせるべきか、具体的なケースを見ていきましょう。
テストファイルやモックファイルをビルドから除外する
開発中はテストファイルが必要ですが、本番用の dist ディレクトリには含めたくないというケースが一般的です。
このような場合、tsconfig.json を用途別に分ける「ベース構成の継承」が推奨されます。
// tsconfig.json (開発・テスト用)
{
"extends": "./tsconfig.base.json",
"include": ["src/**/*"]
}
// tsconfig.build.json (本番ビルド用)
{
"extends": "./tsconfig.json",
"exclude": ["src/**/*.test.ts", "src/__tests__/**/*"]
}
このように設定することで、ビルドコマンド実行時のみ特定のファイルを除外することが可能になります。
外部ライブラリの型定義を制御する
node_modules 全体を除外していても、特定のライブラリの型情報がおかしいせいでエラーが出ることがあります。
その場合は compilerOptions の skipLibCheck: true を併用するのが2026年現在の標準的な手法です。
exclude で node_modules を指定していても、ライブラリを import すれば型チェックは行われるため、この設定が重要になります。
モノレポ構成での管理
複数のパッケージが1つのリポジトリに存在するモノレポ環境では、各パッケージの tsconfig.json で include を厳格に設定します。
自分のパッケージ範囲外のファイルを include しないようにすることで、パッケージ間の境界を明確に保つことができます。
隣接するパッケージのソースコードを直接 import してしまうと、exclude の意図に反してコンパイル対象が肥大化するため、プロジェクト参照(Project References)を活用しましょう。
よくあるトラブルと解決策
設定が正しく反映されない場合、いくつかの典型的な原因が考えられます。
excludeしたはずのファイルで型エラーが出る
前述の通り、インポートパスを確認してください。
意図しない import が残っている場合、TypeScriptはそのファイルを「必要なもの」として認識し続けます。
VS Codeなどのエディタを使用している場合、エディタのキャッシュにより古いエラーが表示され続けることもあります。
その際は TypeScript: Restart TS Server コマンドを実行して、サーバーを再起動してみてください。
includeに含めたのにファイルが認識されない
rootDir や baseUrl の設定との整合性を確認しましょう。
include で指定したパスが rootDir の外側にある場合、TypeScriptは出力ディレクトリの構造を正しく決定できず、エラーを出すことがあります。
また、拡張子の指定(.ts, .tsx)が正しいか、allowJs を true にしていないのに .js ファイルを対象にしていないかを確認してください。
2026年における最新の推奨設定
現代のTypeScriptプロジェクトでは、moduleResolution に bundler を指定することが増えています。
この設定下では、ファイルの解決ルールがより厳格かつ柔軟になります。
include には src フォルダのみを指定し、exclude には dist や artifacts などのビルド生成物を指定するシンプルな構成が、最もトラブルが少ない構成と言えます。
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "bundler",
"skipLibCheck": true,
"strict": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
まとめ
include と exclude は、TypeScriptプロジェクトの健全性を保つための強力なツールです。
include でコンパイル対象の「入り口」を広げ、exclude で不要な「ノイズ」を削ぎ落とすというイメージで設定を行うのがコツです。
しかし、「import文による依存関係はexcludeの設定よりも優先される」というルールは、トラブルシューティングにおいて最も重要な知識となります。
これら二つの違いと優先順位を正しく理解することで、ビルドエラーに悩まされる時間を減らし、本来のコーディング作業に集中できる環境を整えていきましょう。
設定を更新した後は、必ず tsc --showConfig コマンドを使用して、実際にどのファイルが対象になっているかを確認する習慣をつけることをおすすめします。
