TypeScriptの基礎 - tsconfig.json

提供: MochiuWiki : SUSE, EC, PCB

概要

tsconfig.jsonは、TypeScriptプロジェクトにおけるコンパイラの動作を制御する設定ファイルである。

このファイルが存在するディレクトリがプロジェクトルートとして認識され、TypeScriptコンパイラ (tsc) はここで定義されたオプションに従って処理を行う。

tsconfig.jsonファイルが担う主な役割を以下に示す。

tsconfig.jsonファイルの主な役割
役割 説明
コンパイラの動作制御 出力するJavaScriptのバージョンやモジュール形式を指定する。
型チェックの厳格度設定 strictオプション等で型安全性のレベルを調整する。
コンパイル対象の管理 includeおよびexcludeでコンパイル対象ファイルを指定する。
設定の継承 extendsで共通設定を再利用し、環境ごとの設定を分離する。



tsconfig.jsonの基本

ファイルの役割

tsconfig.jsonファイルは、TypeScriptコンパイラへの指示書として機能する。
このファイルをプロジェクトルートに配置することにより、tsc コマンドを引数無しで実行した時に自動的に読み込まれる。

また、コードエディタ (Zed等) もこのファイルを参照することにより、型チェックや補完機能を適切に動作させる。

下表に、主な設定カテゴリを示す。

tsconfig.jsonファイルの主な設定カテゴリ
設定カテゴリ 説明
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"]
 }


下表に、各プロパティの役割を示す。

tsconfig.json プロパティ一覧
プロパティ 説明
compilerOptions コンパイラの動作を制御するオプション群
include コンパイル対象ファイルのグロブパターン
exclude 除外するファイルのグロブパターン (デフォルト: node_modules, outDir)
extends 継承元のtsconfig.jsonへのパス
files コンパイル対象ファイルの明示的なリスト


tsconfig.jsonファイルの生成

tsc --init コマンドを実行すると、コメント付きのデフォルト設定を持つtsconfig.jsonファイルが自動生成される。

tsc --init


生成されたファイルには、多数のオプションがコメントアウトされた状態で含まれており、必要なオプションのコメントを外して有効化する形式になっている。
プロジェクトの要件に合わせて内容を編集する。


主要なコンパイラオプション

strict

strict は、複数の厳格な型チェックオプションを一括で有効化するオプションである。
新規プロジェクトでは、true に設定することを推奨する。

strict: true で有効化されるオプション
オプション 説明
strictNullChecks nullundefined の型を厳密に区別する。
noImplicitAny 型が推論されない値を any として暗黙的に扱わない。
strictFunctionTypes 関数の型チェックを厳格に行う。
strictBindCallApply bind、call、applyの引数型を厳格にチェックする。
strictPropertyInitialization クラスプロパティの初期化を強制する。
noImplicitThis thisの型が暗黙的に any になることを防ぐ。
useUnknownInCatchVariables catch節の変数をunknown型として扱う。
alwaysStrict 全てのファイルにuse strictを付与する。


strictNullChecks

strictNullChecks を有効にすると、nullundefined が独立した型として扱われる。

 // 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のバージョンを指定する。

targetの主な選択肢
説明
ES3 最も古いバージョン
広い互換性が必要な場合
ES5 IEを含む幅広いブラウザ対応が必要な場合
ES2015 アロー関数、クラス、let / const等が使用可能
ES2020 Optional chaining、Nullish coalescing等が使用可能 (推奨)
ES2022 クラスフィールド、top-level await等が使用可能
ESNext 最新のECMAScript仕様に準拠


モダンプロジェクトでは、ES2020以上を推奨する。
ターゲットが高いほど、コンパイル後のコードが簡潔になり、ポリフィルの必要性が減る。

module

module は、出力するJavaScriptのモジュールシステムを指定する。

moduleの主な選択肢
説明
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 文のモジュール解決アルゴリズムを指定する。

moduleResolutionの選択肢
説明
bundler TypeScript 5.0以降推奨
Vite / esbuild等のバンドラ向け
拡張子の省略が可能
node Node.js (CommonJS) の解決アルゴリズム
node16 / nodenext ESMに対応したNode.js向け解決アルゴリズム
classic TypeScript旧来の解決方法
現在は非推奨


Viteプロジェクトでは bundler を指定することにより、Viteのバンドラ動作に最適化した解決が行われる。

jsx

jsx は、.tsxファイル 内のJSX構文の処理方法を指定する。

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"]
    }
 }


下表に、よく使用される値を示す。

lib オプションのよく使用される値
説明
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_modulesbower_componentsjspm_packages および outDir が除外される。


esModuleInterop

esModuleInteroptrue に設定すると、ESモジュールとCommonJSモジュールの相互運用が改善される。

 // esModuleInterop : falseの場合 (CommonJSモジュールのインポート)
 import * as express from 'express';
 
 // esModuleInterop : trueの場合 (より自然な記述が可能)
 import express from 'express';


express等のCommonJSモジュールをESモジュール構文でインポートする場合に必要となる。

isolatedModules

isolatedModulestrue に設定すると、各ファイルを独立して処理できないコード構成を禁止する。

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 のプロパティはマージされる。
    継承側で同じプロパティを再定義すると、そのプロパティが上書きされる。
  • filesincludeexclude は継承側で指定すると完全に上書きされる。
    マージではなく置換となるため注意が必要である。


また、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ツールでそれぞれ最適な設定を適用できる。


関連情報