本文へスキップ
ウェブエンジニア問題集
第11章

tsconfig.jsonの読み方

約12分
この章の目次開く

tsconfig.json はTypeScriptプロジェクトの設定ファイルです。オプションが多く初見では圧倒されますが、実務で重要なものは限られています。

学習者学習者

tsconfig.json のオプションが多すぎて開く気が失せる…。全部理解しないとダメ?

先生先生

全部覚える必要はない。まず strict を有効にして、あとはプロジェクトで問題が出たときにピンポイントで調べれば十分だよ。

VS Codeはどうやって型エラーを表示しているのか

VS CodeでTypeScriptファイルを開くと、tsc コマンドを実行していなくても、型エラーの赤い波線やコード補完が表示されます。この処理には、VS Codeに内蔵されているTypeScript拡張機能と、TypeScriptの tsserver が使われています。

VS Code
  ↓ ファイルを開く・文字を入力する・補完を要求する
VS Code内蔵のTypeScript拡張機能
  ↓ リクエストを送る
tsserver
  ↓ プロジェクトとファイルの状態を管理する
TypeScript Language Service
  ↓ 必要な構文解析・型チェックを行う
型エラー・補完候補・定義位置などをVS Codeへ返す

tsserver は、エディタ向けに動き続けるTypeScriptのサーバープログラムです。開いているファイルやその変更内容、ファイル同士のつながりをメモリ上で管理し、VS Codeからの問い合わせに応答します。

その内部で、型エラーの検出、コード補完、定義への移動、名前の変更などを計算するAPIがTypeScript Language Serviceです。Language Serviceは独立して起動するサーバーではなく、tsserver が利用する機能です。

一方、tsc はターミナルから実行するTypeScriptコンパイラです。tsc と tsserver はTypeScriptの共通の構文解析・型チェック機能を利用しますが、目的と動き方が異なります。

tsctsserver
主な利用者開発者やCIVS Codeなどのエディタ
動き方コマンドとして実行するエディタを開いている間は動き続ける
主な目的型チェックとファイル出力エディタ操作への応答
提供するもの型エラー、コンパイル結果型エラー、コード補完、定義への移動など

したがって、VS Codeに表示されるTypeScript由来の赤い波線は、裏側で tsc を毎回実行した結果ではありません。tsserver がLanguage Serviceから取得し、VS Codeへ返した診断結果です。

VS Codeが使っているtsconfigを確認する

tsserver は、ファイルをTypeScriptプロジェクトの単位で管理します。通常は、そのファイルを対象に含む tsconfig.json を見つけ、そこに書かれた設定を型エラーやコード補完へ反映します。

現在開いているファイルにどの設定ファイルが適用されているかは、VS Codeで確認できます。

  1. 確認したい .ts または .tsx ファイルを開く
  2. コマンドパレットを開く(macOSは Command + Shift + P、Windows/Linuxは Ctrl + Shift + P)
  3. TypeScript: Go to Project Configuration (tsconfig) を実行する

そのファイルが所属しているTypeScriptプロジェクトの tsconfig.json が開きます。複数の設定ファイルがあるプロジェクトでは、予想した設定が適用されているかを確認するのに便利です。

設定ファイルが見つからない場合、VS Codeはそのファイルが設定済みのTypeScriptプロジェクトに属していないことを通知します。このとき tsserver は、開いているファイルを推論されたプロジェクトとして扱い、既定の設定でコード補完や型チェックを行います。

tsconfig.dev.jsonをVS Codeの標準設定にできるか

学習者学習者

プロジェクトルートの tsconfig.json を tsconfig.dev.json に変更して、VS Codeでも標準の設定ファイルとして使うことはできる?

先生先生

tsc には任意の設定ファイルを指定できるけれど、VS Codeに任意のファイル名を標準設定として直接指定することはできないよ。VS Codeにも使わせるなら、入口となる tsconfig.json を残そう。

tsc では、--project(省略形は -p)に設定ファイルのパスを渡せます。そのため、任意の名前の設定ファイルを使って型チェックできます。

npx tsc -p tsconfig.dev.json
bash

しかし、これはこのコマンドで使う設定ファイルを指定しているだけです。VS Codeの tsserver に対して、tsconfig.dev.json をこのプロジェクトの標準設定として直接指定する一般的な設定はありません。tsconfig.dev.json だけに改名すると、VS Codeからは自動認識されなくなります。

設定の本体を tsconfig.dev.json に置きたい場合は、プロジェクトルートに入口となる tsconfig.json を残し、extends で読み込む方法が確実です。

// tsconfig.json
{
  "extends": "./tsconfig.dev.json"
}
json

これなら、VS Codeは tsconfig.json をプロジェクト設定として認識し、その先の tsconfig.dev.json に書かれた設定も適用します。TypeScript: Go to Project Configuration (tsconfig) を実行すると、入口である tsconfig.json が開きます。

strictモード — まずこれを有効にする

strict: true は、複数の厳格チェックをまとめて有効にするフラグです。

{
  "compilerOptions": {
    "strict": true
  }
}
json

strict: true が有効にする主要オプション:

オプション何をチェックするか
strictNullChecksnull / undefined を型レベルで区別する
noImplicitAny型推論できないものに暗黙の any を禁止する
strictFunctionTypes関数の引数型を厳密にチェックする
strictPropertyInitializationclassプロパティの初期化漏れを検出する
// strictNullChecks: true の場合
function greet(name: string | null) {
  // ❌ name.toUpperCase(); // Object is possibly 'null'
  // ✅
  if (name) {
    name.toUpperCase();
  }
}
 
// noImplicitAny: true の場合
// ❌ function process(data) {} // Parameter 'data' implicitly has an 'any' type
// ✅
function process(data: unknown) {}
typescript

target と module — 出力するJSの形式

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext"
  }
}
json
オプション決めることよくある値
targetコンパイル先のJSバージョンES2020, ES2022, ESNext
module出力するモジュール形式ESNext, CommonJS, Node16

target を低くすると、async/await がジェネレータに変換されるなど出力が複雑になります。モダンブラウザやNode.js 18+なら ES2022 以上で問題ありません。

学習者学習者

target と module の違いがよく分からない…。どちらもES何とかを指定するけど何が違うの?

先生先生

target は「どのバージョンのJSに変換するか」で、module は「import/exportをどの形式で出力するか」。Next.jsやViteならフレームワークが適切なデフォルトを設定してくれるから、そのまま使えばOK。

moduleResolution — importの解決方法

{
  "compilerOptions": {
    "moduleResolution": "bundler"
  }
}
json
値使う場面
node従来のNode.js(CommonJS中心)
node16 / nodenextNode.js 16+のESM対応
bundlerVite, Next.js, webpackなどバンドラー経由

bundler はバンドラーが解決してくれる前提で、拡張子なしの import や package.json の exports フィールドを柔軟に扱います。フロントエンド開発では bundler が推奨されています。

paths と baseUrl — パスエイリアス

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
  }
}
json

これで import { Button } from '@/components/Button' のようなエイリアスが使えます。

include と exclude

{
  "include": ["src/**/*", "types/**/*"],
  "exclude": ["node_modules", "dist"]
}
json

include に指定したパターンに一致するファイルだけがコンパイル対象になります。exclude は include の結果からさらに除外するファイルを指定します。

フレームワークのtsconfig

Next.jsやViteは、プロジェクト作成時にtsconfigを自動生成します。

// Next.js が生成する tsconfig.json(抜粋)
{
  "compilerOptions": {
    "target": "ES2017",
    "lib": ["dom", "dom.iterable", "esnext"],
    "module": "esnext",
    "moduleResolution": "bundler",
    "jsx": "preserve",
    "strict": true,
    "paths": {
      "@/*": ["./src/*"]
    }
  }
}
json
tsconfigを読む
フレームワークが生成したtsconfigは、まず触らず意味を理解してから変更する

フレームワークが生成したtsconfigは理由があってその値になっているため、意味が分からないまま変更すると問題が起きやすいです。変更するときは、そのオプションが何を制御しているかを確認してから行います。

実務でよく変更するオプション一覧

オプション用途よくある変更
strict厳密な型チェック新規は true、レガシーは段階的に
targetJS出力バージョン環境に合わせて ES2022 以上
pathsパスエイリアス@/* を追加
skipLibCheck.d.ts のチェック省略ビルド高速化のため true
noUncheckedIndexedAccess配列・オブジェクトのアクセスに undefined を含める安全性を上げるなら true
verbatimModuleSyntaximport type の明示を強制バンドルサイズ最適化

ちゃんと使うためのポイント

  • まず strict: true を有効にする。新規プロジェクトでは必須
  • フレームワーク生成のtsconfigは理解してから変更する
  • moduleResolution: "bundler" がフロントエンド開発の現在の推奨
  • paths の設定はTypeScriptだけでなくバンドラー側も合わせる
  • 困ったときは公式ドキュメントのTSConfig Referenceを確認する

参考リンク

TypeScriptクイズに挑戦するこの章で学んだTypeScriptの知識を、4択クイズでアウトプットして定着させよう