03. tsconfig

検査の厳しさ・出力する JavaScript・import の解決を決める

📅 作成: 2026-08-29 / 更新: 2026-08-29

この章の到達点

この章の内容

  1. tsconfig.json は3つのことを決める
  2. strict — 何を防いでいるか
  3. target と lib — どの JavaScript を出すか
  4. module と moduleResolution — import の解決

03.1 tsconfig.json は3つのことを決める

設定項目は多いが、決めていることは少ない

tsc --init が生成する tsconfig.json には数十の項目が並びます。しかし決めていることは大きく3つです。

何を決めるか主な項目間違えるとどうなるか
検査の厳しさstrict危ないコードが通る。null 由来の実行時エラーが残る
出力する JavaScripttargetliboutDir古い環境で動かない。新しい API が「存在しない」と言われる
import の解決modulemoduleResolutionモジュールが見つからない。実務で最も事故る
tsconfig.json 検査の厳しさ strict 系 危ないコードを弾くか 出力する JavaScript target / lib / outDir どの構文・どの標準 API import の解決 module / moduleResolution どのファイルを指すか 間違えると:危ないコードが通る 間違えると:古い環境で動かない 間違えると:モジュールが見つからない 実務で最も事故る
図 1 — tsconfig.json が決める3つのこと。設定項目は多いが、決めていることは少ない

最小の設定

Node で動かす前提なら、まずこれで足ります。

{
	"compilerOptions": {
		"target": "es2022",
		"module": "nodenext",
		"moduleResolution": "nodenext",
		"strict": true,
		"types": ["node"],
		"outDir": "dist"
	},
	"include": ["src/**/*.ts"]
}

設定を変えてもエラーが変わらないときは、設定が読まれていないことを疑ってください。

02. 実行環境で見たとおり、コマンドラインにファイル名を指定すると tsconfig.json は無視されます。プロジェクト全体を検査するときは npx tsc だけを実行します。

include と exclude

項目意味
include検査の対象。省略すると設定ファイルのある場所以下すべて
excludeinclude から除く。既定で node_modules が入っている
files個別に列挙する。ファイル数が少ないときだけ

「特定のファイルだけ型が付かない」ときは、まず include から漏れていないかを見ます。

03.2 strict — 何を防いでいるか

TypeScript 7 では既定で有効になった

TS7 TypeScript 7 は strict が既定で true です。5 系は既定で false でした。

// strict-test.ts
function greet(name) {
	return "Hello, " + name.toUpperCase();
}
const u: { name?: string } = {};
console.log(u.name.length);
バージョン設定なしで実行結果
TypeScript 7.0.2npx tsc --noEmitエラー2件 TS7006TS18048
TypeScript 5.9.3npx tsc --noEmitエラーなし 素通りする

「5 では通っていたコードが 7 でエラーになる」原因の多くがこれです。

移行時に大量のエラーが出ても、コードが急に壊れたわけではありません。今まで見逃されていた問題が表示されるようになっただけです。一時的に "strict": false にして段階的に直す手もありますが、新規プロジェクトでは必ず有効にしてください。

strict が有効にする主な項目

項目防いでいることエラー番号
noImplicitAny型を書き忘れた引数が暗黙に any になること。1か所の any が下流の検査を無効化する06TS7006
strictNullChecksnullundefined を素通りさせること。最も効果が大きいTS18048
TS2531
strictFunctionTypes関数の引数の型が緩く扱われること(反変チェック)TS2345
strictPropertyInitializationクラスのプロパティが初期化されないまま使われることTS2564
useUnknownInCatchVariablescatch (e)eany になること(11TS18046

実際のエラー

$ npx tsc --noEmit
strict-test.ts(1,16): error TS7006: Parameter 'name' implicitly has an 'any' type.
strict-test.ts(5,13): error TS18048: 'u.name' is possibly 'undefined'.

訳: 引数 'name' は暗黙的に 'any' 型になっています。
    'u.name' は 'undefined' の可能性があります。

個別に切る場合

strict: true のまま、特定の項目だけ切ることもできます。順序が重要で、strict の後に書いた項目が勝ちます。

{
	"compilerOptions": {
		"strict": true,
		"strictPropertyInitialization": false   // ← strict の後なのでこちらが有効
	}
}

Java・C# から来た人へ

strictNullChecks が有効な TypeScript の string は、null を代入できません。Java の String や C# の参照型(null 許容が既定の場合)とは違います。

let s: string = null;         // エラー TS2322
let t: string | null = null;  // これなら通る

C# の nullable 参照型(string?)に近い考え方です。「null かもしれない」ことを型で示さないと、null を入れられません。

03.3 target と lib — どの JavaScript を出すか

target — 出力する構文のレベル

target出力する JavaScript の文法レベルを決めます。古い値にすると、新しい構文が古い書き方に変換されます。

target出力される const x = a ?? b;
es2022const x = a ?? b;(そのまま)
es5var x = a !== null && a !== void 0 ? a : b;(変換される)

Node で動かすなら es2022 以上で構いません。古い値にする理由は、古いブラウザを相手にする場合だけです。

lib — 使える標準 API

lib型として存在する標準 APIを決めます。target から自動で決まるため、通常は書きません。

症状原因
Array.prototype.at が「存在しない」と言われるlib が古い(at は ES2022)
documentwindow が見つからないlibDOM が入っていない(Node 向け設定では正常)
ブラウザ向けなのに document が使えない"lib": ["es2022", "DOM"] を明示する

lib は「型があるか」だけを決めます。実行時に動くかは別問題です。

lib を新しくすれば型エラーは消えますが、古い実行環境で動く保証にはなりません。逆に、実行環境が新しくても lib が古ければ型エラーになります。型と実行時は連動していません01. 背景)。

03.4 module と moduleResolution — import の解決

2つは役割が違う

項目決めること
module出力するモジュール形式(import のまま出すか require にするか)
moduleResolution探し方import "./foo" をどのファイルに対応させるか

Node 向けなら nodenext

ESMCJS Node で動かすなら、両方 nodenext にするのが確実です。package.json"type" を見て、ESM と CJS を自動で切り替えます。

{
	"compilerOptions": {
		"module": "nodenext",
		"moduleResolution": "nodenext"
	}
}
用途modulemoduleResolution
Node で実行するnodenextnodenext
Vite・webpack 等で束ねるesnextbundler
古い CommonJS プロジェクトcommonjsnode10

paths は実行時には効かない

paths でインポートの別名を作れますが、これは型検査だけの機能です。

{
	"compilerOptions": {
		"baseUrl": ".",
		"paths": { "@/*": ["src/*"] }
	}
}
import { greet } from "@/greet";   // tsc は解決できる
                                   // node は解決できない

paths を使うなら、実行側にも同じ設定が要ります。

tsc が出力する JavaScript には @/greet がそのまま残ります。Node はこれを解決できません。バンドラを使うか、package.jsonimports フィールドを使うか、そもそも paths を使わないかを選びます。「型は通るのに実行時に落ちる」典型例です。

設定が合っているかの確かめ方

$ npx tsc --showConfig      # 実際に使われる設定を展開して表示する

継承(extends)や既定値を含めた最終的な設定が出ます。「書いたはずの設定が効かない」ときは、これで実際の値を確認します。