strict が何を有効にするのか、無効だと何が通ってしまうのかを説明できるtarget・module・moduleResolution の役割を区別できるtsc --init が生成する tsconfig.json には数十の項目が並びます。しかし決めていることは大きく3つです。
| 何を決めるか | 主な項目 | 間違えるとどうなるか |
|---|---|---|
| 検査の厳しさ | strict 系 | 危ないコードが通る。null 由来の実行時エラーが残る |
| 出力する JavaScript | target・lib・outDir | 古い環境で動かない。新しい API が「存在しない」と言われる |
import の解決 | module・moduleResolution | モジュールが見つからない。実務で最も事故る |
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 から除く。既定で node_modules が入っている |
files | 個別に列挙する。ファイル数が少ないときだけ |
「特定のファイルだけ型が付かない」ときは、まず include から漏れていないかを見ます。
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.2 | npx tsc --noEmit | エラー2件 TS7006 と TS18048 |
| TypeScript 5.9.3 | npx tsc --noEmit | エラーなし 素通りする |
「5 では通っていたコードが 7 でエラーになる」原因の多くがこれです。
移行時に大量のエラーが出ても、コードが急に壊れたわけではありません。今まで見逃されていた問題が表示されるようになっただけです。一時的に "strict": false にして段階的に直す手もありますが、新規プロジェクトでは必ず有効にしてください。
| 項目 | 防いでいること | エラー番号 |
|---|---|---|
noImplicitAny | 型を書き忘れた引数が暗黙に any になること。1か所の any が下流の検査を無効化する(06) | TS7006 |
strictNullChecks | null・undefined を素通りさせること。最も効果が大きい | TS18048TS2531 |
strictFunctionTypes | 関数の引数の型が緩く扱われること(反変チェック) | TS2345 |
strictPropertyInitialization | クラスのプロパティが初期化されないまま使われること | TS2564 |
useUnknownInCatchVariables | catch (e) の e が any になること(11) | TS18046 |
$ 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 を入れられません。
target は出力する JavaScript の文法レベルを決めます。古い値にすると、新しい構文が古い書き方に変換されます。
| target | 出力される const x = a ?? b; |
|---|---|
es2022 | const x = a ?? b;(そのまま) |
es5 | var x = a !== null && a !== void 0 ? a : b;(変換される) |
Node で動かすなら es2022 以上で構いません。古い値にする理由は、古いブラウザを相手にする場合だけです。
lib は型として存在する標準 APIを決めます。target から自動で決まるため、通常は書きません。
| 症状 | 原因 |
|---|---|
Array.prototype.at が「存在しない」と言われる | lib が古い(at は ES2022) |
document や window が見つからない | lib に DOM が入っていない(Node 向け設定では正常) |
ブラウザ向けなのに document が使えない | "lib": ["es2022", "DOM"] を明示する |
lib は「型があるか」だけを決めます。実行時に動くかは別問題です。
lib を新しくすれば型エラーは消えますが、古い実行環境で動く保証にはなりません。逆に、実行環境が新しくても lib が古ければ型エラーになります。型と実行時は連動していません(01. 背景)。
| 項目 | 決めること |
|---|---|
module | 出力するモジュール形式(import のまま出すか require にするか) |
moduleResolution | 探し方。import "./foo" をどのファイルに対応させるか |
ESMCJS Node で動かすなら、両方 nodenext にするのが確実です。package.json の "type" を見て、ESM と CJS を自動で切り替えます。
{
"compilerOptions": {
"module": "nodenext",
"moduleResolution": "nodenext"
}
}
| 用途 | module | moduleResolution |
|---|---|---|
| Node で実行する | nodenext | nodenext |
| Vite・webpack 等で束ねる | esnext | bundler |
| 古い CommonJS プロジェクト | commonjs | node10 |
paths でインポートの別名を作れますが、これは型検査だけの機能です。
{
"compilerOptions": {
"baseUrl": ".",
"paths": { "@/*": ["src/*"] }
}
}
import { greet } from "@/greet"; // tsc は解決できる
// node は解決できない
paths を使うなら、実行側にも同じ設定が要ります。
tsc が出力する JavaScript には @/greet がそのまま残ります。Node はこれを解決できません。バンドラを使うか、package.json の imports フィールドを使うか、そもそも paths を使わないかを選びます。「型は通るのに実行時に落ちる」典型例です。
$ npx tsc --showConfig # 実際に使われる設定を展開して表示する
継承(extends)や既定値を含めた最終的な設定が出ます。「書いたはずの設定が効かない」ときは、これで実際の値を確認します。
まとめ
| 項目 | この章の結論 |
|---|---|
| 決めていること | 検査の厳しさ・出力する JavaScript・import の解決の3つ |
strict | TypeScript 7 では既定で有効。5 系では無効。移行時のエラー増加の主因 |
target・lib | Node なら es2022 以上。lib は型の有無だけを決め、実行可否とは無関係 |
module 系 | Node なら両方 nodenext。paths は実行時には効かない |
| 確認方法 | npx tsc --showConfig で実際に使われる設定を見る |
次は 04. 型の基本 です。ここから型そのものの話に入ります。04 と 05 は飛ばさないでください。