TypeScriptの基礎 - tsconfig.json
概要
tsconfig.jsonは、TypeScriptプロジェクトにおけるコンパイラの動作を制御する設定ファイルである。
このファイルが存在するディレクトリがプロジェクトルートとして認識され、TypeScriptコンパイラ (tsc) はここで定義されたオプションに従って処理を行う。
tsconfig.jsonファイルが担う主な役割を以下に示す。
| 役割 | 説明 |
|---|---|
| コンパイラの動作制御 | 出力するJavaScriptのバージョンやモジュール形式を指定する。 |
| 型チェックの厳格度設定 | strictオプション等で型安全性のレベルを調整する。 |
| コンパイル対象の管理 | includeおよびexcludeでコンパイル対象ファイルを指定する。 |
| 設定の継承 | extendsで共通設定を再利用し、環境ごとの設定を分離する。 |
tsconfig.jsonの基本
ファイルの役割
tsconfig.jsonファイルは、TypeScriptコンパイラへの指示書として機能する。
このファイルをプロジェクトルートに配置することにより、tsc コマンドを引数無しで実行した時に自動的に読み込まれる。
また、コードエディタ (Zed等) もこのファイルを参照することにより、型チェックや補完機能を適切に動作させる。
下表に、主な設定カテゴリを示す。
| 設定カテゴリ | 説明 |
|---|---|
| compilerOptions | コンパイラの動作を細かく制御するオプション群 |
| include | コンパイル対象に含めるファイルのグロブパターン |
| exclude | コンパイル対象から除外するファイルのグロブパターン |
| extends | 別のtsconfig.jsonから設定を継承するためのパス |
基本構造
tsconfig.jsonファイルの基本的な構造を以下に示す。
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"strict": true,
"outDir": "./dist",
"rootDir": "./src"
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
下表に、各プロパティの役割を示す。
| プロパティ | 説明 |
|---|---|
compilerOptions |
コンパイラの動作を制御するオプション群 |
include |
コンパイル対象ファイルのグロブパターン |
exclude |
除外するファイルのグロブパターン (デフォルト: node_modules, outDir) |
extends |
継承元のtsconfig.jsonへのパス |
files |
コンパイル対象ファイルの明示的なリスト |
tsconfig.jsonファイルの生成
tsc --init コマンドを実行すると、コメント付きのデフォルト設定を持つtsconfig.jsonファイルが自動生成される。
tsc --init
生成されたファイルには、多数のオプションがコメントアウトされた状態で含まれており、必要なオプションのコメントを外して有効化する形式になっている。
プロジェクトの要件に合わせて内容を編集する。
主要なコンパイラオプション
strict
strict は、複数の厳格な型チェックオプションを一括で有効化するオプションである。
新規プロジェクトでは、true に設定することを推奨する。
| オプション | 説明 |
|---|---|
strictNullChecks |
null と undefined の型を厳密に区別する。 |
noImplicitAny |
型が推論されない値を any として暗黙的に扱わない。 |
strictFunctionTypes |
関数の型チェックを厳格に行う。 |
strictBindCallApply |
bind、call、applyの引数型を厳格にチェックする。 |
strictPropertyInitialization |
クラスプロパティの初期化を強制する。 |
noImplicitThis |
thisの型が暗黙的に any になることを防ぐ。 |
useUnknownInCatchVariables |
catch節の変数をunknown型として扱う。 |
alwaysStrict |
全てのファイルにuse strictを付与する。 |
strictNullChecks
strictNullChecks を有効にすると、null と undefined が独立した型として扱われる。
// strictNullChecks : true の場合
let name: string = null; // エラー: nullはstringに代入不可
// nullを許容するにはユニオン型を使用する
let name: string | null = null; // 正常
// undefinedも同様
let value: number | undefined = undefined; // 正常
このオプションを有効にすることで、NullPointerException 相当のバグを型チェックの段階で事前に発見できる。
noImplicitAny
noImplicitAny を有効にすると、TypeScriptが型を推論できない箇所で暗黙的に any 型を割り当てることを禁止する。
// noImplicitAny : true の場合
function greet(name) { // エラー: nameの型注釈が必要
return "Hello, " + name;
}
// 型注釈を明示する必要がある
function greet(name: string) { // 正常
return "Hello, " + name;
}
全てのパラメータと変数に明示的な型注釈が必要となるため、型安全性が向上する。
target
target は、コンパイル後に生成されるJavaScriptのバージョンを指定する。
| 値 | 説明 |
|---|---|
ES3 |
最も古いバージョン 広い互換性が必要な場合 |
ES5 |
IEを含む幅広いブラウザ対応が必要な場合 |
ES2015 |
アロー関数、クラス、let / const等が使用可能 |
ES2020 |
Optional chaining、Nullish coalescing等が使用可能 (推奨) |
ES2022 |
クラスフィールド、top-level await等が使用可能 |
ESNext |
最新のECMAScript仕様に準拠 |
モダンプロジェクトでは、ES2020以上を推奨する。
ターゲットが高いほど、コンパイル後のコードが簡潔になり、ポリフィルの必要性が減る。
module
module は、出力するJavaScriptのモジュールシステムを指定する。
| 値 | 説明 |
|---|---|
CommonJS |
Node.jsのデフォルトモジュール形式 (require / exports) |
ES2015 / ES2020 |
ESモジュール形式 (import / export) |
ESNext |
最新のESモジュール Vite環境で推奨 |
AMD |
非同期モジュール定義 (Webブラウザ向け旧形式) |
UMD |
CommonJSとAMDの両方に対応するユニバーサル形式 |
Viteを使用するフロントエンドプロジェクトでは、ESNextを推奨する。
Node.jsプロジェクトでは、CommonJS または NodeNext を使用する。
moduleResolution
moduleResolution は、import 文のモジュール解決アルゴリズムを指定する。
| 値 | 説明 |
|---|---|
bundler |
TypeScript 5.0以降推奨 Vite / esbuild等のバンドラ向け 拡張子の省略が可能 |
node |
Node.js (CommonJS) の解決アルゴリズム |
node16 / nodenext |
ESMに対応したNode.js向け解決アルゴリズム |
classic |
TypeScript旧来の解決方法 現在は非推奨 |
Viteプロジェクトでは bundler を指定することにより、Viteのバンドラ動作に最適化した解決が行われる。
jsx
jsx は、.tsxファイル 内のJSX構文の処理方法を指定する。
| 値 | 説明 |
|---|---|
react-jsx |
React 17以降推奨jsx() ヘルパー関数に変換import React が不要
|
react |
従来の形式React.createElement() に変換各ファイルで import React が必要
|
preserve |
JSXをそのまま保持 後段のバンドラがJSXを処理する場合に使用 |
React 17以降では、react-jsx を推奨する。
各ファイルへの import React from 'react' の記述が不要になるため、ソースコードが簡潔になる。
paths
paths は、インポートパスのエイリアスを定義する。
baseUrl と組み合わせて使用する。
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"@components/*": ["src/components/*"],
"@utils/*": ["src/utils/*"]
}
}
}
上記の設定により、長い相対パスを簡潔なエイリアスで記述できる。
// pathsエイリアス使用前
import { Button } from '../../../components/Button';
// pathsエイリアス使用後
import { Button } from '@components/Button';
ただし、Viteプロジェクトでは vite.config.tsファイル 側にも同様のエイリアス設定が必要な点に注意する。
その他の重要なオプション
lib
lib は、コンパイル時に利用可能なライブラリの型定義セットを指定する。
{
"compilerOptions": {
"lib": ["ES2020", "DOM", "DOM.Iterable"]
}
}
下表に、よく使用される値を示す。
| 値 | 説明 |
|---|---|
ES2020 |
ES2020の標準APIの型定義 |
DOM |
ブラウザのDOM APIの型定義 (document、window等) |
DOM.Iterable |
NodeList等のDOM要素を for...of でイテレート可能にする型定義
|
ESNext |
最新のECMAScript APIの型定義 |
outDir と rootDir
outDir は、コンパイル後のJavaScriptファイルの出力先ディレクトリを指定し、rootDir はソースファイルのルートディレクトリを指定する。
{
"compilerOptions": {
"rootDir": "./src",
"outDir": "./dist"
}
}
rootDir- ソースファイルのルートとして ./src を指定した場合、src/ディレクトリ 以下のディレクトリ構造を維持したまま出力される。
outDir- コンパイル後のファイルが
./distディレクトリに出力される。
- コンパイル後のファイルが
Viteプロジェクトでは noEmit: true を設定し、tscは型チェックのみを担当させることが一般的である。
include と exclude
include はコンパイル対象のファイルをグロブパターンで指定し、exclude は除外するファイルを指定する。
{
"include": ["src/**/*"],
"exclude": ["node_modules", "dist", "**/*.test.ts"]
}
include- 指定しない場合は、
excludeに含まれない全てのTypeScriptファイルがコンパイル対象になる。
- 指定しない場合は、
exclude- デフォルトで node_modules、bower_components、jspm_packages および outDir が除外される。
esModuleInterop
esModuleInterop を true に設定すると、ESモジュールとCommonJSモジュールの相互運用が改善される。
// esModuleInterop : falseの場合 (CommonJSモジュールのインポート)
import * as express from 'express';
// esModuleInterop : trueの場合 (より自然な記述が可能)
import express from 'express';
express等のCommonJSモジュールをESモジュール構文でインポートする場合に必要となる。
isolatedModules
isolatedModules を true に設定すると、各ファイルを独立して処理できないコード構成を禁止する。
esbuildやSWCは単一ファイルを個別にトランスパイルするため、ファイルをまたいだ型情報を参照できない。
このオプションを有効にすることで、これらのツールとの互換性を確保できる。
// isolatedModules : true の場合、型のみの再exportは明示が必要
export { SomeType } from './types'; // エラー : 型のみのexportには、export typeを使用する必要がある。
// 正しい記述
export type { SomeType } from './types'; // 型専用export構文を明示的に使用
Viteプロジェクトでは true を推奨する。
Tauri + Viteプロジェクトでの推奨設定
tsconfig.jsonファイルの推奨設定
Tauri + Viteプロジェクトでの推奨設定を以下に示す。
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"moduleResolution": "bundler",
"jsx": "react-jsx",
"strict": true,
"esModuleInterop": true,
"isolatedModules": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"noEmit": true
},
"include": ["src"]
}
各オプションの選定理由
下表に、各オプションを選定した理由を示す。
| オプション | 選定理由 |
|---|---|
target: "ES2020" |
TauriがサポートするWebViewがES2020を十分にサポートしているため、 モダンな構文を利用できる。 |
module: "ESNext" |
ViteはESモジュールを前提として最適化を行うため、ESNextが最適である。 |
lib: ["ES2020", "DOM", "DOM.Iterable"] |
WebブラウザAPIとES2020の標準APIを使用するフロントエンド開発に必要な型定義を含む。 |
moduleResolution: "bundler" |
Viteのバンドラ動作に最適化されており、 拡張子の省略や exports フィールドの解決に対応する。
|
jsx: "react-jsx" |
React 17以降の推奨形式であり、各ファイルへの import React が不要になる。
|
strict: true |
最大レベルの型安全性を確保し、潜在的なバグを早期に検出する。 |
esModuleInterop: true |
CommonJSモジュールをESモジュール構文でインポートできるようにし、 既存ライブラリとの互換性を確保する。 |
isolatedModules: true |
Viteがesbuildでトランスパイルするため、各ファイルを独立して処理できる構成を強制する。 |
skipLibCheck: true |
外部ライブラリの型定義ファイル (.d.ts) の型チェックをスキップし、 ビルド速度を向上させる。 |
forceConsistentCasingInFileNames: true |
ファイル名の大文字/小文字の一貫性を強制し、 大文字・小文字を区別しないファイルシステムでの問題を防ぐ。 |
resolveJsonModule: true |
JSONファイルをモジュールとしてインポートできるようにする。 |
noEmit: true |
tscはJavaScriptファイルを生成せず、型チェックのみを行う。 実際のトランスパイルはViteが担当する。 |
tsconfigの継承 (extends)
基本的な使用方法
extends プロパティを使用することにより、別のtsconfig.jsonファイルから設定を継承できる。
継承元の設定をベースとして、継承側で必要なオプションのみを上書きすることが可能である。
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"jsx": "react-jsx",
"lib": ["ES2020", "DOM", "DOM.Iterable"]
}
}
継承における重要なルールを以下に示す。
compilerOptionsのプロパティはマージされる。- 継承側で同じプロパティを再定義すると、そのプロパティが上書きされる。
- files、include、exclude は継承側で指定すると完全に上書きされる。
- マージではなく置換となるため注意が必要である。
また、npmパッケージとして配布されている公式の基本設定を使用することもできる。
npm install --save-dev @tsconfig/node18
{
"extends": "@tsconfig/node18/tsconfig.json",
"compilerOptions": {
"outDir": "./dist"
}
}
設定ファイルの分割例
大規模なプロジェクトでは、複数の環境向けに設定ファイルを分割することが有効である。
フロントエンドとバックエンドを含むモノリポ構成での分割例を以下に示す。
- tsconfig.base.json (共通設定)
{ "compilerOptions": { "target": "ES2020", "module": "ESNext", "strict": true, "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "skipLibCheck": true } }
- tsconfig.app.json (フロントエンド用)
{ "extends": "./tsconfig.base.json", "compilerOptions": { "moduleResolution": "bundler", "jsx": "react-jsx", "lib": ["ES2020", "DOM", "DOM.Iterable"], "isolatedModules": true, "noEmit": true }, "include": ["src"] }
- tsconfig.node.json (Node.jsツール用)
{ "extends": "./tsconfig.base.json", "compilerOptions": { "module": "CommonJS", "moduleResolution": "node", "lib": ["ES2020"], "outDir": "./dist" }, "include": ["scripts", "vite.config.ts"] }
この分割により、アプリケーションコードとNode.jsツールでそれぞれ最適な設定を適用できる。
関連情報