【TypeScript】tsconfig.json 完全ガイド|全オプション解説と目的別おすすめ設定

【TypeScript】tsconfig.json 完全ガイド|全オプション解説と目的別おすすめ設定 TypeScript

TypeScriptプロジェクトの中心にあるのが tsconfig.json です。このファイルひとつで、コンパイラの挙動型チェックの厳しさモジュールの解決方法出力形式など、プロジェクト全体の設定をコントロールできます。

しかし、tsconfig.json には100以上のオプションがあり、初めて見ると「どれを設定すればいいの?」と迷ってしまいがちです。公式ドキュメントを読んでも、オプション同士の関係性や「実務でどう組み合わせるか」が分かりにくいのが現状です。

この記事では、tsconfig.json の全体像から主要オプションの詳細解説、そして目的別のおすすめ設定テンプレートまで、実務で必要な知識を体系的にまとめました。「このオプションは何のためにあるのか」「どんな値を設定すべきか」を具体的なコード例とともに解説します。

この記事で学べること

  • tsconfig.json の役割基本構造(compilerOptions, include, exclude, extends, files, references)
  • 型チェック系オプション(strict, strictNullChecks, noImplicitAny, noUncheckedIndexedAccess 等)
  • モジュール系オプション(module, moduleResolution, paths, baseUrl, esModuleInterop 等)
  • 出力系オプション(target, lib, outDir, declaration, sourceMap 等)
  • JavaScript連携オプション(allowJs, checkJs)とその他のオプション(jsx, isolatedModules, verbatimModuleSyntax 等)
  • extends で設定を継承する方法(モノレポ対応)
  • Project References(複合プロジェクト構成)
  • 目的別おすすめ設定テンプレート(Webフロント / Node.js / React(Vite) / Next.js / ライブラリ開発 / monorepo)
  • strictモードの段階的導入(既存JSプロジェクトの移行戦略)
  • よくある設定ミスとトラブルシューティング
  • 設定オプション早見表

前提知識:この記事はTypeScriptの基本的な型の書き方を理解している方を対象としています。型の基本から学びたい方は【TypeScript】型の書き方 完全入門を先にお読みください。

スポンサーリンク
  1. tsconfig.json とは
    1. tsconfig.json の役割
    2. tsc –init で tsconfig.json を生成する
  2. tsconfig.json の基本構造
  3. compilerOptions: 型チェック系オプション
    1. strict(厳格モード一括ON)
    2. strictNullChecks
    3. noImplicitAny
    4. strictFunctionTypes
    5. strictBindCallApply
    6. strictPropertyInitialization
    7. noImplicitThis
    8. noImplicitReturns
    9. noFallthroughCasesInSwitch
    10. noUncheckedIndexedAccess
    11. exactOptionalPropertyTypes
    12. 型チェック系オプション一覧まとめ
  4. compilerOptions: モジュール系オプション
    1. module
    2. moduleResolution
    3. esModuleInterop
    4. resolveJsonModule
    5. baseUrl と paths(パスエイリアス)
    6. rootDir
    7. rootDirs
  5. compilerOptions: 出力系オプション
    1. target
    2. lib
    3. outDir / outFile
    4. declaration / declarationDir / declarationMap
    5. sourceMap / inlineSourceMap
    6. removeComments
    7. noEmit
    8. emitDeclarationOnly
    9. 出力系オプション一覧まとめ
  6. compilerOptions: JavaScript 連携オプション
    1. allowJs
    2. checkJs
    3. maxNodeModuleJsDepth
  7. compilerOptions: その他の重要なオプション
    1. skipLibCheck
    2. forceConsistentCasingInFileNames
    3. isolatedModules
    4. verbatimModuleSyntax(TypeScript 5.0+)
    5. jsx / jsxFactory / jsxFragmentFactory / jsxImportSource
  8. include / exclude / files の使い分け
    1. include
    2. exclude
    3. files
    4. include / exclude / files の優先順位
  9. extends で設定を継承する
    1. 基本的な使い方
    2. npm パッケージの tsconfig を継承する
  10. Project References(複数プロジェクト構成)
  11. 目的別おすすめ設定テンプレート
    1. Web フロントエンド(バニラ TypeScript)
    2. Node.js(バックエンド / CLI ツール)
    3. React(Vite)
    4. Next.js
    5. npm ライブラリ開発
    6. monorepo(共通設定 + パッケージ個別設定)
  12. strict モードを段階的に導入する方法
    1. ステップ1: allowJs + checkJs で JS ファイルを受け入れる
    2. ステップ2: 新規ファイルは .ts で、既存ファイルは徐々にリネーム
    3. ステップ3: strict のサブオプションを1つずつ有効化
    4. ステップ4: strict: true に切り替え
  13. よくある設定ミスとトラブルシューティング
    1. 1. module と moduleResolution の不一致
    2. 2. paths を設定したのにランタイムで Module not found
    3. 3. exclude で除外したファイルがまだコンパイルされる
    4. 4. Cannot find module エラー(型定義ファイル)
    5. 5. lib に DOM を含めていないのにブラウザ API を使っている
    6. 6. outDir と rootDir の設定不備
    7. 7. isolatedModules 関連のエラー
    8. 8. 設定変更がエディタに反映されない
  14. まとめ
    1. 設定オプション早見表

tsconfig.json とは

tsconfig.json は、TypeScriptプロジェクトの設定ファイルです。プロジェクトのルートディレクトリに配置し、TypeScriptコンパイラ(tsc)に対して「どのファイルをコンパイルするか」「どのようにコンパイルするか」「どの程度厳密に型チェックするか」を指示します。

tsconfig.json の役割

tsconfig.json が担う役割は主に以下の4つです。

役割 説明 関連オプション例
型チェックの制御 どの程度厳密に型チェックを行うかを設定 strict, strictNullChecks, noImplicitAny
モジュール解決の設定 import/export の解決方法やパスエイリアスを設定 module, moduleResolution, paths
出力の制御 コンパイル結果の出力先やフォーマットを設定 target, outDir, declaration
対象ファイルの指定 コンパイル対象のファイルやディレクトリを指定 include, exclude, files

tsc –init で tsconfig.json を生成する

tsconfig.json を一から手書きする必要はありません。TypeScriptコンパイラの --init フラグを使えば、テンプレート付きの tsconfig.json が自動生成されます。

ターミナル
# TypeScript をグローバルインストール(未インストールの場合)
npm install -g typescript

# プロジェクトディレクトリで tsconfig.json を生成
cd my-project
tsc --init

# npx を使う場合(グローバルインストール不要)
npx tsc --init

生成されたファイルには主要なオプションがコメント付きで記載されているため、必要に応じてコメントを外して設定を有効にできます。ただし、生成されるテンプレートは汎用的な設定なので、プロジェクトの種類に合わせたカスタマイズが重要です(後述の「目的別おすすめ設定テンプレート」を参照)。

注意:tsconfig.json はJSON形式ですが、TypeScript公式はコメント(///* */)を許容しています。これはJSON5ではなく、TypeScript独自のJSON拡張パーサー(JSONC: JSON with Comments)によるものです。

tsconfig.json の基本構造

tsconfig.json はトップレベルに複数のプロパティを持つJSON構造です。まずは全体像を把握しましょう。

tsconfig.json の全体構造
{
  // 他の tsconfig を継承(オプション)
  "extends": "./tsconfig.base.json",

  // コンパイラオプション(メイン設定)
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "strict": true,
    // ...その他のオプション
  },

  // コンパイル対象のファイル/ディレクトリ(glob パターン)
  "include": ["src/**/*"],

  // コンパイル対象から除外するファイル/ディレクトリ
  "exclude": ["node_modules", "dist"],

  // コンパイル対象ファイルを個別に指定(include の代わり)
  "files": ["src/index.ts"],

  // Project References(複合プロジェクト構成)
  "references": [
    { "path": "./packages/core" },
    { "path": "./packages/ui" }
  ]
}

各トップレベルプロパティの役割を整理します。

プロパティ 説明 必須?
compilerOptions コンパイラの動作を制御する各種オプション。型チェック、モジュール解決、出力形式などを設定 ほぼ必須
include コンパイル対象に含めるファイルをglobパターンで指定。省略すると全 .ts / .tsx ファイルが対象 推奨
exclude include で指定した範囲から除外するファイルを指定。デフォルトで node_modules 等が除外される 任意
files コンパイル対象ファイルを個別に指定。include/exclude より優先される 任意
extends 別の tsconfig.json を継承する。共通設定を基底ファイルにまとめ、プロジェクト固有の設定だけ上書きできる 任意
references Project References で参照する他のプロジェクトを指定。モノレポで活用 任意

ポイント:この記事ではまず compilerOptions の各オプションをカテゴリ別に詳しく解説し、その後で include / exclude / extends / references を取り上げます。

compilerOptions: 型チェック系オプション

型チェック系のオプションは、TypeScriptの最大の強みである静的型検査の厳しさをコントロールします。ここを適切に設定することで、バグの早期発見とコードの安全性が大きく向上します。

strict(厳格モード一括ON)

strict は、複数の厳格な型チェックオプションを一括で有効化するメタオプションです。新規プロジェクトでは true に設定することが強く推奨されています。

tsconfig.json
{
  "compilerOptions": {
    "strict": true
    // これだけで以下のオプションがすべて true になる:
    // - strictNullChecks
    // - strictFunctionTypes
    // - strictBindCallApply
    // - strictPropertyInitialization
    // - noImplicitAny
    // - noImplicitThis
    // - alwaysStrict
    // - useUnknownInCatchVariables
  }
}

ポイント:strict: true を設定した上で、個別のオプションを false にすることも可能です。例えば "strict": true, "strictPropertyInitialization": false とすれば、strictPropertyInitialization 以外の厳格チェックがすべて有効になります。

以下、strict に含まれる各サブオプションと、strict に含まれないが重要な型チェックオプションを個別に解説します。

strictNullChecks

strictNullChecks は、nullundefined他の型と区別するかどうかを制御します。TypeScript で最も重要なオプションのひとつです。

設定値 動作
true(推奨) null / undefined は独立した型として扱われる。変数に代入するには型注釈で明示的に許可する必要がある
false null / undefined はすべての型に代入可能(安全性が低下)
strictNullChecks の効果
// strictNullChecks: true の場合
let name: string = "Alice";
name = null;      // エラー: Type 'null' is not assignable to type 'string'
name = undefined; // エラー: Type 'undefined' is not assignable to type 'string'

// null を許容したい場合は Union 型で明示する
let nickname: string | null = "Bob";
nickname = null;    // OK

// 使用時にはナローイングが必要
if (nickname !== null) {
  console.log(nickname.toUpperCase()); // OK: string に絞り込まれている
}

注意:strictNullChecks: false にすると、実行時に TypeError: Cannot read properties of null が発生するリスクが大幅に高まります。特別な理由がない限り、必ず true にしましょう。

noImplicitAny

noImplicitAny は、型注釈が省略されて TypeScript が型を推論できない場合に暗黙の anyを許容するかどうかを制御します。

noImplicitAny の効果
// noImplicitAny: true の場合
function greet(name) {
  // エラー: Parameter 'name' implicitly has an 'any' type (TS7006)
  return `Hello, ${name}`;
}

// 修正: 型注釈を追加する
function greetFixed(name: string) {
  return `Hello, ${name}`;
}

// 推論可能な場合はエラーにならない
const numbers = [1, 2, 3];
numbers.map(n => n * 2); // OK: n は number と推論される

strictFunctionTypes

strictFunctionTypes は、関数の引数の型チェックを反変(contravariant)にします。具体的には、コールバック関数の引数の型がより広い型に代入されることを禁止します。

strictFunctionTypes の効果
type Animal = { name: string };
type Dog = { name: string; breed: string };

type AnimalHandler = (animal: Animal) => void;

// strictFunctionTypes: true の場合
const dogHandler: AnimalHandler = (dog: Dog) => {
  console.log(dog.breed);
  // エラー! Animal に breed プロパティはないため危険
};

// AnimalHandler として呼ばれると Animal が渡される可能性がある
// その場合 dog.breed は undefined になってしまう

strictBindCallApply

strictBindCallApply は、Function.prototype.bindcallapply の引数を厳密に型チェックします。

strictBindCallApply の効果
function add(a: number, b: number): number {
  return a + b;
}

// strictBindCallApply: true の場合
add.call(undefined, 1, 2);       // OK
add.call(undefined, "1", 2);     // エラー: string は number に代入できない
add.apply(undefined, [1, 2]);     // OK
add.apply(undefined, [1]);        // エラー: 引数の数が足りない

const boundAdd = add.bind(undefined, 1);
boundAdd(2);   // OK: (b: number) => number に推論される
boundAdd("2"); // エラー: string は number に代入できない

strictPropertyInitialization

strictPropertyInitialization は、クラスのプロパティがコンストラクタ内で確実に初期化されているかを検査します。strictNullCheckstrue の場合にのみ有効です。

strictPropertyInitialization の効果
class User {
  name: string;  // エラー: コンストラクタで初期化されていない
  age: number;

  constructor(age: number) {
    this.age = age;
    // name が初期化されていない!
  }
}

// 解決策1: コンストラクタで初期化する
class UserFixed1 {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
}

// 解決策2: デフォルト値を設定する
class UserFixed2 {
  name: string = "";
}

// 解決策3: undefined を許容する
class UserFixed3 {
  name: string | undefined;
}

// 解決策4: 明示的代入アサーション(非推奨 - 最終手段)
class UserFixed4 {
  name!: string;  // ! で「後で必ず初期化する」と宣言
}

noImplicitThis

noImplicitThis は、this の型が any に推論される場合にエラーを報告します。クラスメソッドやイベントハンドラで this のコンテキストを見失うバグを防ぎます。

noImplicitThis の効果
// noImplicitThis: true の場合
function standalone() {
  return this; // エラー: 'this' implicitly has type 'any'
}

// 修正: this パラメータを明示する
function standaloneFixed(this: Window) {
  return this; // OK: this は Window 型
}

noImplicitReturns

noImplicitReturns は、関数のすべてのコードパスが明示的に値を返すことを要求します。strict には含まれないため、個別に設定する必要があります。

noImplicitReturns の効果
// noImplicitReturns: true の場合
function getLabel(code: number): string {
  if (code === 1) {
    return "OK";
  }
  // エラー: Not all code paths return a value
  // code !== 1 の場合に return がない
}

// 修正: すべてのパスで値を返す
function getLabelFixed(code: number): string {
  if (code === 1) {
    return "OK";
  }
  return "Unknown";
}

noFallthroughCasesInSwitch

noFallthroughCasesInSwitch は、switch 文で breakreturn のない case のフォールスルーを禁止します。意図しないフォールスルーバグを防ぎます。

noFallthroughCasesInSwitch の効果
function getArea(shape: "circle" | "square") {
  switch (shape) {
    case "circle":
      console.log("円");
      // エラー: Fallthrough case in switch(break がない)
    case "square":
      console.log("四角");
      break;
  }
}

noUncheckedIndexedAccess

noUncheckedIndexedAccess は、配列やオブジェクトのインデックスアクセスの結果に自動で | undefined を付与します。strict には含まれませんが、安全性を高める非常に有用なオプションです。

noUncheckedIndexedAccess の効果
const colors: string[] = ["red", "blue", "green"];

// noUncheckedIndexedAccess: false(デフォルト)
const first = colors[0]; // string 型 - 存在しない添字でも string
const tenth = colors[9]; // string 型 - 実際は undefined なのに!

// noUncheckedIndexedAccess: true
const first2 = colors[0]; // string | undefined
const tenth2 = colors[9]; // string | undefined

// 使用前にチェックが必要になる
if (first2 !== undefined) {
  console.log(first2.toUpperCase()); // OK
}

// Record のインデックスアクセスにも適用される
const config: Record<string, number> = { width: 100 };
const val = config["height"]; // number | undefined

ポイント:noUncheckedIndexedAccessstrict に含まれていませんが、新規プロジェクトでは true にすることを強くおすすめします。配列の範囲外アクセスに起因するバグを防げます。

exactOptionalPropertyTypes

exactOptionalPropertyTypes は、オプショナルプロパティに undefined明示的に代入することを禁止します。「プロパティが存在しない」ことと「プロパティが undefined」であることを区別したい場合に有用です。

exactOptionalPropertyTypes の効果
interface Theme {
  color?: string; // オプショナル: string | undefined
}

// exactOptionalPropertyTypes: true の場合
const theme1: Theme = {};              // OK: プロパティなし
const theme2: Theme = { color: "red" }; // OK: string
const theme3: Theme = { color: undefined }; // エラー!

// undefined も許可したい場合は明示的に書く
interface ThemeV2 {
  color?: string | undefined;
}

型チェック系オプション一覧まとめ

オプション strict に含まれる? 推奨値 概要
strict true 以下の strict 系オプションを一括有効化
strictNullChecks Yes true null / undefined を区別する
noImplicitAny Yes true 暗黙の any を禁止
strictFunctionTypes Yes true 関数引数の反変チェック
strictBindCallApply Yes true bind/call/apply の型チェック
strictPropertyInitialization Yes true クラスプロパティの初期化チェック
noImplicitThis Yes true 暗黙の this: any を禁止
alwaysStrict Yes true 出力に “use strict” を付与
useUnknownInCatchVariables Yes true catch 変数を unknown にする
noImplicitReturns No true 暗黙の return undefined を禁止
noFallthroughCasesInSwitch No true switch の意図しないフォールスルーを禁止
noUncheckedIndexedAccess No true 添字アクセスに | undefined を付与
exactOptionalPropertyTypes No 任意 オプショナルへの undefined 代入を禁止

compilerOptions: モジュール系オプション

モジュール系のオプションは、TypeScriptが import / export をどのように解決・変換するかを制御します。プロジェクトの実行環境(ブラウザ / Node.js)やバンドラーとの連携に直結する重要な設定です。

module

module は、コンパイル後のJavaScriptが使用するモジュールシステムを指定します。import/export がどのような形式に変換されるかを決定します。

モジュール形式 用途
commonjs CommonJS (require / module.exports) Node.js(従来型)
es2015 / es6 ES Modules (import / export) モダンブラウザ、バンドラー
es2020 ES2020 (dynamic import 対応) 動的インポートが必要な場合
es2022 ES2022 (top-level await 対応) 最新のバンドラー環境
esnext 最新の ES Modules Vite / webpack 等のバンドラー使用時(推奨)
node16 Node.js 16+ ネイティブ ESM Node.js で ESM を使う場合(推奨)
nodenext 最新の Node.js ESM Node.js の最新 ESM 仕様に追従
preserve 入力をそのまま保持 バンドラーに変換を任せる場合(TS 5.4+)

ポイント:Vite / webpack / Rollup 等のバンドラーを使用する場合は "esnext"、Node.js で直接実行する場合は "node16" または "nodenext" を選びましょう。

moduleResolution

moduleResolution は、import 文のモジュールパスをどのアルゴリズムで解決するかを指定します。module と密接に関連しています。

解決方法 対応する module
node(classic Node) Node.js の require() と同じ解決アルゴリズム commonjs
node16 Node.js 16+ の ESM / CJS デュアル解決 node16
nodenext Node.js の最新解決アルゴリズム nodenext
bundler バンドラー向け解決(拡張子省略可、条件付きエクスポート対応) esnext, preserve
module と moduleResolution の推奨組み合わせ
// バンドラー使用(Vite / webpack / Rollup 等)
{
  "module": "ESNext",
  "moduleResolution": "bundler"
}

// Node.js(ESM)
{
  "module": "NodeNext",
  "moduleResolution": "nodenext"
}

// Node.js(CommonJS)
{
  "module": "commonjs",
  "moduleResolution": "node"
}

esModuleInterop

esModuleInterop は、CommonJSモジュールを ESM の import 構文で自然に読み込めるようにする互換レイヤーを追加します。

esModuleInterop の効果
// esModuleInterop: false の場合(CommonJS モジュールの読み込み)
import * as express from "express";  // 名前空間インポートが必要
import * as path from "path";

// esModuleInterop: true の場合(推奨)
import express from "express";  // デフォルトインポートが使える!
import path from "path";

// React も同様
import React from "react";  // esModuleInterop: true で可能

注意:esModuleInterop: true にすると allowSyntheticDefaultImports も自動で true になります。ほとんどのプロジェクトで true が推奨されます。

resolveJsonModule

resolveJsonModuletrue にすると、.json ファイルを import できるようになり、さらに型推論も効きます。

resolveJsonModule の効果
// resolveJsonModule: true
import packageJson from "./package.json";

console.log(packageJson.name);    // 型推論: string
console.log(packageJson.version); // 型推論: string

// 設定ファイルの読み込みにも便利
import config from "./config.json";
// config の各プロパティに型が付く

baseUrl と paths(パスエイリアス)

baseUrlpaths を組み合わせると、パスエイリアス(import のショートカット)を設定できます。深いディレクトリ構造での相対パス地獄を解消します。

tsconfig.json – パスエイリアス設定
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"],
      "@components/*": ["src/components/*"],
      "@utils/*": ["src/utils/*"],
      "@types/*": ["src/types/*"]
    }
  }
}
パスエイリアスの使用例
// Before: 相対パス地獄
import { Button } from "../../../components/Button";
import { formatDate } from "../../../utils/date";
import type { User } from "../../../types/user";

// After: パスエイリアスでスッキリ
import { Button } from "@components/Button";
import { formatDate } from "@utils/date";
import type { User } from "@types/user";

注意:paths は TypeScript のコンパイラにパスの解決方法を教えるだけで、実行時の変換は行いません。Vite なら vite.config.tsresolve.alias、webpack なら resolve.alias、Node.js なら tsconfig-paths パッケージなど、ランタイム側でも同じエイリアス設定が必要です。

rootDir

rootDir は、ソースファイルのルートディレクトリを指定します。出力ディレクトリの構造に影響します。

rootDir の効果
// ディレクトリ構造
// project/
//   src/
//     index.ts
//     utils/helper.ts

// rootDir: "src" + outDir: "dist" の場合
// dist/
//   index.js        ← src/ が取り除かれる
//   utils/helper.js

// rootDir 未指定 + outDir: "dist" の場合
// dist/
//   src/             ← src/ がそのまま残る
//     index.js
//     utils/helper.js

rootDirs

rootDirs は、複数のディレクトリを仮想的に1つのルートに統合します。ビルド時に生成されるファイルと手書きのソースファイルを同じディレクトリにあるかのように扱いたい場合に使います。

rootDirs の設定例
{
  "compilerOptions": {
    "rootDirs": [
      "src",
      "generated"  // 自動生成ファイル
    ]
  }
}

// src/app.ts から generated/api-types.ts を相対パスで参照できる
// import { ApiResponse } from "./api-types";

compilerOptions: 出力系オプション

出力系のオプションは、TypeScriptのコンパイル結果としてどんなJavaScriptファイルを生成するかを制御します。出力先ディレクトリ、ECMAScriptバージョン、型定義ファイル、ソースマップなどを設定します。

target

target は、コンパイル後の JavaScript が準拠するECMAScript バージョンを指定します。TypeScript はこのバージョンで利用できない構文を自動的にダウンレベル変換します。

主要な機能 対応環境
ES5 IE11 対応。アロー関数、const/let を変換 IE11 + 古いブラウザ
ES2015 (ES6) クラス、アロー関数、Promise モダンブラウザ
ES2016 Array.includes, べき乗演算子 モダンブラウザ
ES2017 async/await モダンブラウザ / Node 8+
ES2018 rest/spread プロパティ、非同期イテレータ Node 10+
ES2019 Array.flat, Object.fromEntries Node 12+
ES2020 Optional Chaining, Nullish Coalescing, BigInt Node 14+
ES2021 String.replaceAll, 論理代入 Node 16+
ES2022 Top-level await, Array.at, クラスフィールド Node 18+(推奨)
ESNext 最新仕様(常に最新に追従) 最新環境のみ
target によるダウンレベル変換の例
// TypeScript ソースコード
const greet = (name: string) => `Hello, ${name}!`;

// target: "ES2015" 以上 → そのまま
const greet = (name) => `Hello, ${name}!`;

// target: "ES5" → アロー関数とテンプレートリテラルが変換される
var greet = function(name) {
  return "Hello, " + name + "!";
};

ポイント:2025年以降の新規プロジェクトでは "ES2022" を基本として選ぶのがおすすめです。IE対応が不要なモダン環境であれば、不要なダウンレベル変換を避けてパフォーマンスとバンドルサイズを最適化できます。

lib

lib は、TypeScript が組み込み型定義として読み込むライブラリ一覧を指定します。target を設定すると対応する lib が自動で含まれますが、手動で上書きも可能です。

lib の設定例
{
  "compilerOptions": {
    "target": "ES2022",
    "lib": [
      "ES2022",     // ES2022 の組み込み型(Array.at 等)
      "DOM",        // ブラウザ DOM API(document, window 等)
      "DOM.Iterable" // NodeList の for...of 対応
    ]
  }
}

// Node.js の場合は DOM を含めない
{
  "compilerOptions": {
    "target": "ES2022",
    "lib": ["ES2022"] // DOM を含めない → document 等にアクセスするとエラー
  }
}
lib 値 含まれる型 用途
ESxxxx 各 ES バージョンの組み込みオブジェクト 基本(必須)
DOM document, window, HTMLElement 等 ブラウザ向け
DOM.Iterable NodeList, HTMLCollection の iterable ブラウザ向け(for…of 対応)
WebWorker Web Worker 環境の型 Worker 向け
ESNext 最新のECMAScript提案の型 最新機能を使いたい場合

outDir / outFile

outDir はコンパイル結果の出力先ディレクトリを指定します。outFile は出力を1つのファイルにバンドルします(module が amd または system の場合のみ)。

outDir の設定
{
  "compilerOptions": {
    "outDir": "dist",   // コンパイル結果を dist/ に出力
    "rootDir": "src"    // ソースのルートを src/ に設定
  }
}

// src/index.ts       → dist/index.js
// src/utils/date.ts  → dist/utils/date.js

declaration / declarationDir / declarationMap

型定義ファイル(.d.ts)の生成に関するオプションです。ライブラリを公開する場合に特に重要です。

オプション デフォルト 説明
declaration false .d.ts ファイルを生成する
declarationDir outDir と同じ .d.ts ファイルの出力先ディレクトリ
declarationMap false .d.ts.map ファイルを生成(元の .ts ファイルへのマッピング)
ライブラリ開発向け設定
{
  "compilerOptions": {
    "declaration": true,        // .d.ts を生成
    "declarationDir": "types",  // types/ ディレクトリに出力
    "declarationMap": true,     // .d.ts.map も生成(Go to Definition 対応)
    "outDir": "dist"
  }
}

// 出力結果:
// dist/index.js          (実行用 JS)
// types/index.d.ts       (型定義)
// types/index.d.ts.map   (ソースマップ)

sourceMap / inlineSourceMap

sourceMaptrue にすると、コンパイル後の JavaScript と元の TypeScript ソースを対応づけるソースマップ.js.map)が生成されます。デバッグ時にブラウザの DevTools や VS Code で元の TypeScript コードを確認できます。

sourceMap の設定
{
  "compilerOptions": {
    "sourceMap": true,         // .js.map ファイルを生成
    // "inlineSourceMap": true,  // 代替: JS ファイル内にマップを埋め込む
    // ↑ sourceMap と inlineSourceMap は同時に使えない
  }
}

// sourceMap: true の出力:
// dist/index.js
// dist/index.js.map  ← ソースマップ

removeComments

removeCommentstrue にすると、コンパイル後の JavaScript からコメントが削除されます。バンドルサイズの削減に貢献しますが、通常はバンドラーの minification で処理されるため、設定の優先度は低いです。

noEmit

noEmittrue にすると、TypeScript コンパイラは型チェックのみを行い、JavaScript ファイルを出力しません。Vite や webpack など、バンドラー側で JavaScript への変換を行う場合に使用します。

noEmit の典型的な使い方
// Vite + React プロジェクトでの典型パターン
{
  "compilerOptions": {
    "noEmit": true // tsc は型チェックだけ。JS変換は Vite(esbuild) に任せる
  }
}

// package.json の scripts
// "type-check": "tsc --noEmit"
// "build": "vite build"  ← JS の変換とバンドルは Vite が担当

emitDeclarationOnly

emitDeclarationOnlytrue にすると、.d.ts ファイルのみ出力し、.js ファイルは生成しません。JavaScript への変換はバンドラーに任せつつ、型定義だけ tsc で生成する場合に使います。

emitDeclarationOnly の使用例
// ライブラリ開発: JS は tsup/Rollup で、型定義は tsc で生成
{
  "compilerOptions": {
    "declaration": true,
    "emitDeclarationOnly": true,
    "outDir": "dist"
  }
}

出力系オプション一覧まとめ

オプション 概要
target string 出力する JS の ECMAScript バージョン
lib string[] 組み込み型定義ライブラリの指定
outDir string 出力先ディレクトリ
outFile string 出力を1ファイルにバンドル(AMD/System のみ)
declaration boolean .d.ts 型定義ファイルを生成
declarationDir string .d.ts の出力先ディレクトリ
declarationMap boolean .d.ts.map ソースマップを生成
sourceMap boolean .js.map ソースマップを生成
inlineSourceMap boolean JS ファイル内にソースマップを埋め込む
removeComments boolean 出力からコメントを削除
noEmit boolean JS を出力せず型チェックのみ
emitDeclarationOnly boolean .d.ts のみ出力(.js は出力しない)

compilerOptions: JavaScript 連携オプション

TypeScript プロジェクトで既存の JavaScript ファイルを扱う場合に使用するオプションです。既存 JS プロジェクトの段階的な TypeScript 移行で特に重要です。

allowJs

allowJstrue にすると、TypeScript プロジェクト内で .js / .jsx ファイルをコンパイル対象に含めることができます。TypeScript と JavaScript が混在するプロジェクトで必須です。

allowJs の使用例
{
  "compilerOptions": {
    "allowJs": true,   // .js ファイルをコンパイル対象に含める
    "checkJs": false  // .js ファイルの型チェックは行わない(段階移行の初期段階)
  }
}

// .ts ファイルから .js ファイルを import できる
// src/app.ts
import { legacy } from "./legacy-module"; // legacy-module.js

checkJs

checkJstrue にすると、.js ファイルに対しても型チェックが行われます。JSDoc コメントから型情報を推論します。allowJs: true が前提です。

checkJs で JS ファイルを型チェック
// utils.js - JSDoc で型情報を付与

/**
 * @param {string} name
 * @param {number} age
 * @returns {string}
 */
function introduce(name, age) {
  return `${name} (${age}歳)`;
}

introduce(123, "not a number"); // checkJs: true → 型エラー!

// 特定ファイルでチェックを無効化したい場合
// @ts-nocheck をファイル先頭に追加

maxNodeModuleJsDepth

maxNodeModuleJsDepth は、node_modules 内の JavaScript ファイルを型チェックする最大深度を指定します。デフォルトは 0(チェックしない)です。通常はデフォルトのままで問題ありません。

compilerOptions: その他の重要なオプション

カテゴリに収まりにくいが、実務で頻繁に使用される重要なオプションをまとめます。

skipLibCheck

skipLibChecktrue にすると、.d.ts(型定義)ファイルの型チェックをスキップします。コンパイル速度が大幅に向上し、サードパーティライブラリ間の型の不整合によるエラーも回避できます。

tsconfig.json
{
  "compilerOptions": {
    "skipLibCheck": true  // 推奨: .d.ts の型チェックをスキップ
  }
}

ポイント:ほとんどのプロジェクトで skipLibCheck: true が推奨されます。node_modules 内の型定義の不整合でビルドが壊れることを防ぎ、コンパイル速度も改善されます。

forceConsistentCasingInFileNames

forceConsistentCasingInFileNamestrue にすると、import のファイル名の大文字小文字を厳密にチェックします。macOS / Windows のように大文字小文字を区別しないファイルシステムでも、Linux 上では区別されるため、CI/CD 環境でのエラーを防ぎます。

forceConsistentCasingInFileNames の効果
// ファイル名: UserService.ts

// forceConsistentCasingInFileNames: true の場合
import { UserService } from "./userservice"; // エラー! 大文字小文字が一致しない
import { UserService } from "./UserService"; // OK

isolatedModules

isolatedModulestrue にすると、各ファイルが独立してトランスパイルされることを前提とした制約が追加されます。Babel、esbuild、SWC など、ファイル単位でトランスパイルするツールと組み合わせる場合に必須です。

isolatedModules で禁止されるパターン
// isolatedModules: true の場合

// 1. 型のみの re-export は禁止
export { SomeType } from "./types"; // エラー(型か値か判別できない)
export type { SomeType } from "./types"; // OK: type キーワードで明示

// 2. const enum は禁止(ファイル横断の解析が必要なため)
const enum Direction { Up, Down } // エラー
enum Direction { Up, Down }       // OK: 通常の enum は許可

// 3. import/export のないファイルはモジュールとして扱えない
// 最低でも export {} を追加する

verbatimModuleSyntax(TypeScript 5.0+)

verbatimModuleSyntax は TypeScript 5.0 で導入された新しいオプションで、isolatedModulesimportsNotUsedAsValuespreserveValueImports統合・置換するものです。

verbatimModuleSyntax の効果
// verbatimModuleSyntax: true の場合

// import type で明示しないと型のみのインポートはエラー
import { User } from "./types";      // エラー(User が型のみの場合)
import type { User } from "./types"; // OK: import type で明示

// 値と型を混在させる場合
import { createUser, type User } from "./user"; // OK: インライン type

ポイント:TypeScript 5.0 以降の新規プロジェクトでは、isolatedModules の代わりに verbatimModuleSyntax: true を使うことを検討しましょう。型と値の区別がより明確になり、バンドラーとの互換性も向上します。

jsx / jsxFactory / jsxFragmentFactory / jsxImportSource

JSX(React の JSX 構文)の変換方法を制御するオプション群です。

jsx の値 変換方法 用途
react React.createElement() に変換 React 16 以前
react-jsx 新しい JSX Transform(_jsx() React 17+(推奨)
react-jsxdev 開発用の JSX Transform(デバッグ情報付き) 開発環境用
preserve JSX をそのまま出力(.jsx 拡張子) バンドラーに変換を任せる場合
react-native JSX をそのまま出力(.js 拡張子) React Native
React プロジェクトの JSX 設定
// React 17+ 推奨設定
{
  "compilerOptions": {
    "jsx": "react-jsx" // import React from "react" が不要に
  }
}

// Vite + React の場合は preserve が一般的
{
  "compilerOptions": {
    "jsx": "preserve" // Vite (esbuild) が JSX を処理する
  }
}

include / exclude / files の使い分け

コンパイル対象のファイルを制御する3つのトップレベルプロパティの使い分けを整理します。

include

include は、コンパイル対象に含めるファイルをglob パターンで指定します。最もよく使われるプロパティです。

include の設定例
{
  "include": [
    "src",          // src ディレクトリ以下の全 .ts/.tsx/.d.ts
    "src/**/*",     // 上と同じ(明示的にサブディレクトリを含む)
    "*.config.ts"  // ルートの設定ファイル
  ]
}

// サポートされる glob パターン
// *     : 0文字以上の任意の文字列(ディレクトリ区切りを除く)
// ?     : 任意の1文字
// **/   : 任意の深さのサブディレクトリ

注意:include を省略すると、tsconfig.json があるディレクトリ以下のすべての .ts / .tsx / .d.ts ファイルが対象になります(exclude で除外されたものを除く)。意図しないファイルが含まれるのを防ぐため、include は明示的に設定することをおすすめします。

exclude

exclude は、include でマッチしたファイルの中から除外するファイルを指定します。

exclude の設定例
{
  "include": ["src"],
  "exclude": [
    "node_modules",      // デフォルトで除外(明示も可)
    "dist",              // 出力ディレクトリ
    "**/*.test.ts",      // テストファイル
    "**/*.spec.ts",      // テストファイル
    "coverage",          // カバレッジ出力
    "**/__tests__/**"    // テストディレクトリ
  ]
}

ポイント:exclude を省略した場合、node_modulesbower_componentsjspm_packages、および outDir で指定したディレクトリがデフォルトで除外されます。exclude を明示的に設定した場合はこのデフォルトが上書きされるので、node_modules も含めるのを忘れないでください。

files

files は、コンパイル対象ファイルを個別に指定します。glob パターンは使えません。

include / exclude / files の優先順位

条件 動作
files で指定されたファイル exclude に関係なく常にコンパイル対象
include にマッチ & exclude にマッチしない コンパイル対象
include にマッチ & exclude にもマッチ 除外される
対象ファイルから import されたファイル exclude に含まれていてもコンパイル対象(依存関係解決)

注意:exclude で除外したファイルでも、コンパイル対象のファイルから import されていれば自動的にコンパイル対象に含まれますexclude はあくまで「直接の対象から除外する」だけで、依存関係経由の読み込みは防げません。

extends で設定を継承する

extends を使うと、別の tsconfig.json の設定を継承して、差分だけを上書きできます。共通設定を基底ファイルにまとめることで、設定の重複を排除できます。

基本的な使い方

tsconfig.base.json(基底設定)
{
  "compilerOptions": {
    "strict": true,
    "target": "ES2022",
    "moduleResolution": "bundler",
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  }
}
tsconfig.json(プロジェクト固有設定)
{
  "extends": "./tsconfig.base.json",
  "compilerOptions": {
    "module": "ESNext",
    "jsx": "react-jsx",
    "outDir": "dist"
  },
  "include": ["src"]
}

npm パッケージの tsconfig を継承する

@tsconfig/ シリーズの npm パッケージを使えば、フレームワーク別の推奨設定を簡単に継承できます。

npm パッケージの tsconfig を利用
// インストール
npm install -D @tsconfig/node18

// tsconfig.json
{
  "extends": "@tsconfig/node18/tsconfig.json",
  "compilerOptions": {
    "outDir": "dist"
  },
  "include": ["src"]
}

// 利用可能なパッケージ例:
// @tsconfig/node18, @tsconfig/node20, @tsconfig/strictest, @tsconfig/recommended

Project References(複数プロジェクト構成)

Project References は、大規模なプロジェクトやモノレポを複数のサブプロジェクトに分割し、それぞれを独立してビルドできる仕組みです。tsc --buildtsc -b)と組み合わせて使います。

Project References の利点

  • インクリメンタルビルド: 変更のあったサブプロジェクトだけ再ビルド(大幅な高速化)
  • 論理的な分離: サブプロジェクト間の依存関係を明示的に宣言
  • 高速なエディタ対応: エディタが各サブプロジェクトを独立して処理
  • 安全な公開境界: .d.ts 経由の参照で内部実装の漏洩を防止
Project References の構成例
// ルート tsconfig.json
{
  "files": [],
  "references": [
    { "path": "./packages/core" },
    { "path": "./packages/ui" }
  ]
}

// packages/core/tsconfig.json(参照されるプロジェクト)
{
  "compilerOptions": {
    "composite": true,   // 必須: Project References で参照される場合
    "declaration": true, // composite で自動 true
    "outDir": "dist"
  },
  "include": ["src"]
}

// packages/ui/tsconfig.json(core に依存)
{
  "compilerOptions": { "composite": true, "outDir": "dist" },
  "include": ["src"],
  "references": [{ "path": "../core" }]
}
ビルドコマンド
# 全プロジェクトをビルド(依存関係順に自動ビルド)
tsc --build

# 特定のプロジェクトだけビルド
tsc --build packages/core

# クリーンビルド / ウォッチモード
tsc --build --clean
tsc --build --watch

ポイント:Project References を使う場合、参照されるプロジェクトには "composite": true が必須です。このオプションは declaration: trueincremental: true を自動で有効にし、他プロジェクトから .d.ts 経由で参照できるようにします。

目的別おすすめ設定テンプレート

プロジェクトの種類に応じた実践的な tsconfig.json テンプレートを紹介します。そのままコピーして使えるよう、各オプションにコメントで説明を付けています。

Web フロントエンド(バニラ TypeScript)

React / Vue などのフレームワークを使わず、TypeScript + バンドラーで Web フロントエンドを開発する場合の設定です。

Web フロントエンド向け tsconfig.json
{
  "compilerOptions": {
    /* 型チェック */
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,

    /* モジュール */
    "module": "ESNext",
    "moduleResolution": "bundler",
    "esModuleInterop": true,
    "resolveJsonModule": true,
    "isolatedModules": true,

    /* 出力 */
    "target": "ES2022",
    "lib": ["ES2022", "DOM", "DOM.Iterable"],
    "noEmit": true,

    /* その他 */
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src"]
}

Node.js(バックエンド / CLI ツール)

Node.js で動作するバックエンドアプリケーションや CLI ツールの設定です。DOM 型は含めず、Node.js 環境に最適化しています。

Node.js 向け tsconfig.json
{
  "compilerOptions": {
    /* 型チェック */
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "noImplicitReturns": true,

    /* モジュール */
    "module": "NodeNext",
    "moduleResolution": "nodenext",
    "esModuleInterop": true,
    "resolveJsonModule": true,

    /* 出力 */
    "target": "ES2022",
    "lib": ["ES2022"],
    "outDir": "dist",
    "rootDir": "src",
    "sourceMap": true,

    /* その他 */
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src"],
  "exclude": ["node_modules", "dist"]
}

React(Vite)

Vite + React のプロジェクト向け設定です。Vite(esbuild)が JavaScript 変換を担当するため、tsc は型チェックのみ行います。

Vite + React 向け tsconfig.json
{
  "compilerOptions": {
    /* 型チェック */
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "noImplicitReturns": true,

    /* モジュール */
    "module": "ESNext",
    "moduleResolution": "bundler",
    "esModuleInterop": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "allowImportingTsExtensions": true,

    /* 出力 */
    "target": "ES2022",
    "lib": ["ES2022", "DOM", "DOM.Iterable"],
    "noEmit": true,

    /* JSX */
    "jsx": "react-jsx",

    /* パスエイリアス(vite.config.ts でも設定が必要) */
    "baseUrl": ".",
    "paths": { "@/*": ["src/*"] },

    /* その他 */
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src"]
}

Next.js

Next.js プロジェクトの設定です。Next.js は next dev / next build 実行時に tsconfig.json を自動生成・補完しますが、以下の設定をベースにカスタマイズできます。

Next.js 向け tsconfig.json
{
  "compilerOptions": {
    /* 型チェック */
    "strict": true,
    "noUncheckedIndexedAccess": true,

    /* モジュール */
    "module": "ESNext",
    "moduleResolution": "bundler",
    "esModuleInterop": true,
    "resolveJsonModule": true,
    "isolatedModules": true,

    /* 出力 */
    "target": "ES2022",
    "lib": ["ES2022", "DOM", "DOM.Iterable"],
    "noEmit": true,

    /* JSX - Next.js が自動設定する場合もある */
    "jsx": "preserve",

    /* Next.js 固有 */
    "incremental": true,
    "allowJs": true,
    "baseUrl": ".",
    "paths": { "@/*": ["./src/*"] },

    /* Next.js プラグイン */
    "plugins": [{ "name": "next" }],

    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
  "exclude": ["node_modules"]
}

npm ライブラリ開発

npm で公開するライブラリを開発する場合の設定です。.d.ts(型定義ファイル)の生成が必須で、CJS / ESM のデュアル出力を考慮する場合もあります。

ライブラリ開発向け tsconfig.json
{
  "compilerOptions": {
    /* 型チェック(最大限に厳格) */
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "exactOptionalPropertyTypes": true,

    /* モジュール */
    "module": "ESNext",
    "moduleResolution": "bundler",
    "esModuleInterop": true,
    "verbatimModuleSyntax": true,

    /* 出力 */
    "target": "ES2022",
    "lib": ["ES2022"],
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true,
    "outDir": "dist",
    "rootDir": "src",

    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src"],
  "exclude": ["node_modules", "dist", "**/*.test.ts"]
}

monorepo(共通設定 + パッケージ個別設定)

Turborepo / Nx / pnpm workspace 等のモノレポ構成では、ルートに共通設定を置き、各パッケージで継承します。

monorepo ルート: tsconfig.base.json
{
  "compilerOptions": {
    "strict": true,
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "esModuleInterop": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "noUncheckedIndexedAccess": true,
    "noImplicitReturns": true,
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true
  }
}
packages/web/tsconfig.json(フロントエンド用パッケージ)
{
  "extends": "../../tsconfig.base.json",
  "compilerOptions": {
    "lib": ["ES2022", "DOM", "DOM.Iterable"],
    "jsx": "react-jsx",
    "noEmit": true
  },
  "include": ["src"]
}
packages/api/tsconfig.json(バックエンド用パッケージ)
{
  "extends": "../../tsconfig.base.json",
  "compilerOptions": {
    "lib": ["ES2022"],
    "outDir": "dist",
    "rootDir": "src"
  },
  "include": ["src"],
  "exclude": ["node_modules", "dist"]
}

strict モードを段階的に導入する方法

既存の JavaScript プロジェクトを TypeScript に移行する場合や、strict: false で始めたプロジェクトに strict モードを導入する場合、一度にすべてを有効にすると大量のエラーが発生して対処が困難になります。ここでは、段階的に strict を導入する実践的な戦略を紹介します。

ステップ1: allowJs + checkJs で JS ファイルを受け入れる

まず、既存の .js ファイルをそのまま TypeScript プロジェクトに含められるようにします。

ステップ1: JS 受け入れ段階
{
  "compilerOptions": {
    "allowJs": true,   // .js ファイルをコンパイル対象に
    "checkJs": false,  // まだ型チェックはしない
    "strict": false,   // strict はまだ無効
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "esModuleInterop": true,
    "skipLibCheck": true
  }
}

ステップ2: 新規ファイルは .ts で、既存ファイルは徐々にリネーム

新しいファイルは .ts で作成し、既存の .js ファイルは優先度の高いものから順に .ts にリネームしていきます。

ステップ3: strict のサブオプションを1つずつ有効化

strict: true を一気に入れる代わりに、サブオプションを影響の小さいものから順番に有効化します。

ステップ3: 段階的に strict サブオプションを有効化
{
  "compilerOptions": {
    // Phase 1: 影響が小さいものから
    "alwaysStrict": true,               // "use strict" を付与(ほぼ影響なし)
    "strictBindCallApply": true,         // bind/call/apply のチェック
    "forceConsistentCasingInFileNames": true,

    // Phase 2: 関数周りの厳格化
    "noImplicitThis": true,             // this の暗黙 any を禁止
    "strictFunctionTypes": true,        // 関数引数の反変チェック

    // Phase 3: 最も影響が大きいもの
    "noImplicitAny": true,              // 暗黙の any を禁止(大量のエラーが出やすい)
    "strictNullChecks": true,           // null/undefined の区別(最も影響大)

    // Phase 4: クラス関連
    "strictPropertyInitialization": true,
    "useUnknownInCatchVariables": true
  }
}

ステップ4: strict: true に切り替え

すべてのサブオプションが true になったら、個別のオプションを削除して "strict": true に統合します。

最終形: strict: true
{
  "compilerOptions": {
    "strict": true,  // すべてのサブオプションを一括で有効化
    "noUncheckedIndexedAccess": true,  // strict に含まれないので個別指定
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true
  }
}

段階的導入のコツ

  • 各フェーズごとにPR を分けてマージすると、レビューとロールバックがしやすい
  • // @ts-expect-error// @ts-ignore を一時的に使い、後で解消する計画を立てる
  • noImplicitAnystrictNullChecks が最も修正量が多い。この2つは十分な時間を確保する
  • CI に tsc --noEmit を組み込み、型エラーが増えないようにゲートを設ける

よくある設定ミスとトラブルシューティング

tsconfig.json の設定で陥りやすいミスと、その解決方法をまとめます。

1. module と moduleResolution の不一致

modulemoduleResolution の組み合わせが不適切だと、モジュールの解決が正しく行われず、import エラーが発生します。

NG な組み合わせ 問題 正しい組み合わせ
module: "ESNext" + moduleResolution: "node" ESM の機能(条件付きエクスポート等)が使えない moduleResolution: "bundler"
module: "NodeNext" + moduleResolution: "bundler" Node.js の ESM 解決と互換性がない moduleResolution: "nodenext"
module: "commonjs" + moduleResolution: "bundler" CommonJS にはバンドラー解決が不適切 moduleResolution: "node"

2. paths を設定したのにランタイムで Module not found

paths は TypeScript コンパイラ(型チェック)にのみ影響し、実行時のモジュール解決には反映されません。バンドラーやランタイム側でも同じエイリアスを設定する必要があります。

paths の設定に対応するランタイム設定
// tsconfig.json の paths
"paths": { "@/*": ["src/*"] }

// Vite: vite.config.ts
resolve: { alias: { '@': path.resolve(__dirname, 'src') } }

// webpack: webpack.config.js
resolve: { alias: { '@': path.resolve(__dirname, 'src') } }

// Node.js: tsconfig-paths パッケージをインストール
npm install -D tsconfig-paths
node -r tsconfig-paths/register dist/index.js

3. exclude で除外したファイルがまだコンパイルされる

exclude で指定したファイルが依然としてコンパイルされる場合、それは他のコンパイル対象ファイルから import されている可能性があります。exclude は直接のファイル指定からの除外であり、依存関係の解決は防げません。

解決策:そのファイルへの import 文を削除するか、テスト用の tsconfig.test.json を別途作成してテストファイル専用の設定を分離しましょう。

4. Cannot find module エラー(型定義ファイル)

サードパーティライブラリを import したときに Cannot find moduleCould not find a declaration file エラーが出る場合の対処法です。

型定義ファイルの解決方法
// 解決策1: @types パッケージをインストール
npm install -D @types/lodash
npm install -D @types/express

// 解決策2: @types がない場合は declare module で宣言
// src/types/custom.d.ts
declare module "some-untyped-lib" {
  const content: any;
  export default content;
}

// 解決策3: CSS / SVG 等のアセットファイル
// src/types/assets.d.ts
declare module "*.css" {
  const classes: { [key: string]: string };
  export default classes;
}
declare module "*.svg" {
  const src: string;
  export default src;
}

5. lib に DOM を含めていないのにブラウザ API を使っている

Node.js 向けプロジェクトで "lib": ["ES2022"] のみ設定しているのに、documentwindow を参照するとエラーになります。逆に、Node.js プロジェクトで意図せず DOM を含めると、window が存在しない環境でもエラーにならず、バグの原因になります。

6. outDir と rootDir の設定不備

rootDir を設定し忘れると、出力ディレクトリの構造が期待と異なることがあります。

rootDir 設定のありなしの違い
// rootDir 未設定の場合
// dist/src/index.js  ← src/ が残ってしまう

// rootDir: "src" を設定した場合
// dist/index.js      ← 期待通りの構造

7. isolatedModules 関連のエラー

isolatedModules: true を設定した場合、以下のパターンがエラーになります。対処法を確認しましょう。

エラーパターン 原因 解決方法
export { X } で X が型のみ 型か値か判別できない export type { X } に変更
const enum の使用 ファイル横断の解析が必要 通常の enum に変更
import/export のないファイル モジュールとして認識されない export {} を追加

8. 設定変更がエディタに反映されない

tsconfig.json を変更してもエディタ(VS Code)のエラー表示が更新されない場合は、TypeScript サーバーの再起動が必要です。

VS Code で TypeScript サーバーを再起動
// VS Code のコマンドパレット(Ctrl+Shift+P / Cmd+Shift+P)で:
TypeScript: Restart TS Server

// または、VS Code を再起動(Ctrl+Shift+P):
Developer: Reload Window

まとめ

tsconfig.json は TypeScript プロジェクトの「設計図」であり、適切に設定することで型安全性開発者体験ビルドパフォーマンスのすべてが向上します。この記事で解説した内容の要点を振り返りましょう。

tsconfig.json 設定のベストプラクティス

  • 新規プロジェクトでは必ず "strict": true を設定する
  • noUncheckedIndexedAccessnoImplicitReturnsnoFallthroughCasesInSwitch も合わせて有効化する
  • modulemoduleResolution は環境に合った正しい組み合わせを選ぶ
  • バンドラー使用時は noEmit: true で tsc は型チェック専用にする
  • skipLibCheck: true でコンパイル速度を最適化する
  • パスエイリアス(paths)を使う場合はランタイム側にも同じ設定をする
  • モノレポでは extends で共通設定を継承し、各パッケージで差分だけ上書きする
  • 既存プロジェクトの strict 化は段階的に行い、フェーズごとにPRを分ける

設定オプション早見表

主要なオプションの推奨値をプロジェクト種別ごとにまとめました。

オプション Web Frontend Node.js React (Vite) Next.js Library
strict true true true true true
target ES2022 ES2022 ES2022 ES2022 ES2022
module ESNext NodeNext ESNext ESNext ESNext
moduleResolution bundler nodenext bundler bundler bundler
lib ES2022, DOM ES2022 ES2022, DOM ES2022, DOM ES2022
jsx react-jsx preserve
noEmit true false true true false
declaration true
esModuleInterop true true true true true
isolatedModules true true true
skipLibCheck true true true true true

tsconfig.json は「設定して終わり」ではなく、プロジェクトの成長に合わせて定期的に見直すことが重要です。TypeScript のバージョンアップで新しいオプション(verbatimModuleSyntax など)が追加されることもあるので、公式ドキュメントの tsconfig リファレンスもチェックしておきましょう。

この記事が、あなたの TypeScript プロジェクトの最適な設定を見つける助けになれば幸いです。

TypeScript シリーズ記事