実務におけるtsconfig設定⚙️

## はじめに
tsconfigでの各設定の意味・用途について、気になったので記載します。
下記で取り扱う設定は、私が参画する実務プロジェクトでのconfig設定になります。

## 目次

1. [tsconfig.jsonって何？](#-tsconfigjsonって何)
2. [tsconfig.jsonの目的・メリット](#-tsconfigjsonの目的メリット)
3. [tsconfigの各設定](#-tsconfigの各設定)
4. [まとめ](#-まとめ)
5. [参考文献](#-参考文献)

## 🪄 tsconfig.jsonって何？
`tsconfig.json` は、TypeScript プロジェクトのルートディレクトリに配置される設定ファイルです。

TypeScript コンパイラ（tsc コマンドなど）がプロジェクトをコンパイルする際に、**どのような設定やオプションを使用してコンパイルを行うかを指定するためのファイル**になります。

## 🪄 tsconfig.jsonの目的・メリット
### tsconfig.json がある場合
#### 1. コンパイラオプションの指定
* どのバージョンのJavaScriptを出力するか (target)
* どのモジュールシステムを使用するか (module)
* どのライブラリの型定義を含めるか (lib)
* 型チェックの厳格さ（strict オプションやその関連オプション）
* ソースマップを生成するか (sourceMap)
* 出力ディレクトリを指定するか (outDir)。

👉 様々なコンパイラの振る舞いを細かく設定可能です！

#### 2. プロジェクトのルートと対象ファイルの定義
`include` や `exclude` オプションを使って、コンパイル対象に含めるファイルや除外するファイルを指定できます。
👉 コンパイラはプロジェクト全体の構造を把握できます。

#### 3. IDEやツールの連携
多くのIDEやビルドツール（Webpack, Parcelなど）は `tsconfig.json` ファイルを読み込み、その設定に基づいてコード補完、エラーチェック、コードジャンプなどの機能を提供します。
👉 これにより、開発体験が向上します。

#### 4. コマンドラインオプションの省略
`tsconfig.json` に設定を書いておけば、コンパイル時に毎回長いコマンドラインオプションを指定する必要がなくなります。
👉 単に `tsc` コマンドを実行するだけで、ファイルに書かれた設定に基づいてコンパイルが行われます。

### tsconfig.json がない場合
* `tsconfig.json` ファイルが存在しない場合、TypeScript コンパイラはいくつかのデフォルト設定で動作します。
* プロジェクトのルートやコンパイル対象のファイルはコマンドライン引数や、現在のディレクトリ以下のすべての `.ts` ファイルなどから推測されることになります。
**ただし、これは非推奨です。**

👉 `tsconfig.json` はTypeScriptプロジェクトの「設計図」のようなもの
👉 プロジェクトの構造、コンパイル方法、型チェックのルールなどを一元管理するための非常に重要なファイル
👉 TypeScript を使用したプロジェクト開発においては、通常、最初にこのファイルを適切に設定することから始まる♪

## 🪄 tsconfigの各設定
```js
{
  // TypeScriptコンパイラの動作を制御するオプション群
  "compilerOptions": {
    /* 基本設定 (Base Settings) */
    /*
     コンパイル後のJavaScriptのバージョンを指定します。
     "es2022" は最新のJavaScript機能（トップレベルawaitなど）を含むため、実行環境が対応している必要があります。
     より古い環境向けには "es5" や "es6" (es2015) などを指定します。
    */
    "target": "es2022",

    /*
     生成されるJavaScriptのモジュールシステムを指定します。
     "commonjs" はNode.jsで一般的な形式です。
     ブラウザ向けやES Modulesを使用する場合は "esnext" や "es2015", "amd", "system" などを指定します。
    */
    "module": "commonjs",

    /*
     コンパイルされたJavaScriptファイルや型定義ファイルの出力先ディレクトリを指定します。
     ここでは、ソースディレクトリと同じ階層にある "./dist" ディレクトリに出力されます。
    */
    "outDir": "./dist",

    /*
     コンパイル時に、ソースファイルから型定義ファイル（.d.ts）を生成するかどうかを指定します。
     ライブラリとして公開する場合や、JavaScriptファイルから型を利用したい場合に true にします。
    */
    "declaration": true,

    /*
     declaration: true の場合に、生成される .d.ts ファイルに対応するソースマップファイル（.d.ts.map）を生成するかどうかを指定します。
     これにより、エディタで型定義を見た際に、その型が元のTypeScriptコードのどこで定義されているか（定義元）にジャンプできるようになります。デバッグに役立ちます。
    */
    "declarationMap": true,

    /*
     コンパイル後のJavaScriptファイルに対応するソースマップファイル（.js.map）を生成するかどうかを指定します。
     これにより、ブラウザのデバッグツールなどで、コンパイル後のJavaScriptではなく元のTypeScriptコードを見ながらデバッグできるようになります。
     こちらが一般的なソースマップ生成設定です。declarationMapとは用途が異なります。
    */
    "sourceMap": true,

    /*
     インクリメンタルコンパイルを有効にするかどうかを指定します。
     以前のコンパイル結果をキャッシュし、変更があったファイルのみを再コンパイルすることで、コンパイル時間を短縮します。大規模プロジェクトで有効です。
    */
    "incremental": true,

    /* 
     コンパイル後のJavaScriptファイルからコメントを削除するかどうかを指定します。
     false にするとコメントが残ります。特にライセンス情報などを残したい場合に false にすることがあります。
    */
    "removeComments": false,

    /* 型チェック設定 (Type Checking) */
    /*
     TypeScriptの最も厳格な型チェックオプション群をまとめて有効にするフラグです。
     true にすると、noImplicitAny, strictNullChecks, strictFunctionTypes など、以下のコメントアウトされている厳格オプションの多くが自動的に true になります。
     個別の厳格オプションを制御したい場合は、この strict を false にして、個別に true/false を設定します。
    */
    "strict": true,

    /*
     "strict": true が有効な場合、以下も自動的に true になります。
     型注釈がない変数、関数の引数、返り値などで、TypeScriptが型を推論できず any 型と判断した場合にエラーとします。
     これにより、意図しない any 型の使用を防ぎ、より安全なコードになります
    */
    // "noImplicitAny": true,

    /*
     "strict": true が有効な場合、これも自動的に true になります。
     null および undefined を型システム上で厳密に扱います。
     null または undefined の可能性がある変数へのプロパティアクセスやメソッド呼び出しをコンパイルエラーとします。
     これにより、実行時の NullPointerException などのエラーを防ぎます。
    */
    // "strictNullChecks": true,

    /* 
     "strict": true が有効な場合、これも自動的に true になります。
     関数を別の関数型の変数に代入する際に、引数の型についてより厳密なチェックを行います。
     これにより、関数の型の互換性に関する潜在的なバグを防ぎます。
    */
    // "strictFunctionTypes": true,

    /* 
     "strict": true が有効な場合、これも自動的に true になります。
     Function.prototype.bind, call, apply メソッドを使用する際に、関数のシグネチャと引数の型が一致しているかより厳密にチェックします。
     これにより、これらのメソッドの誤用による型エラーを防ぎます。
    */
    // "strictBindCallApply": true,

    /* 
     "strict": true が有効な場合、これも自動的に true になることが期待されますが、クラスによってはコンストラクタでの初期化を強制しないケースもあるため、strict とは別に明示的に制御されることもあります。
     クラスのインスタンスプロパティが、コンストラクタ内で明確に初期化されているかチェックします。初期化されていない場合はエラーとします。
     これにより、未初期化のプロパティへのアクセスを防ぎます。
    */
    // "strictPropertyInitialization": true,

    /*
     "strict": true が有効な場合、これも自動的に true になります。
     関数内の this の型が TypeScript によって推論できず、any 型と判断された場合にエラーとします。
     これにより、this の意図しないコンテキストでの使用を防ぎます。
    */
    // "noImplicitThis": true,

    /* 
     "strict": true が有効な場合、これも自動的に true になります。
     生成されるJavaScriptファイルの先頭に 'use strict'; ディレクティブを常に追加します。
     これにより、JavaScriptコードがStrict Modeで実行されるようになり、より安全で予測可能な動作になります。
    */
    // "alwaysStrict": true,

    /* 追加チェック (Additional Checks) */
    /* 
     ソースコード内で宣言されたローカル変数（関数スコープやブロックスコープ内の変数）が一度も使用されていない場合にエラーまたは警告を出力します。
     不要なコードやタイプミスによる未使用変数を検出するのに役立ちます。
    */
    "noUnusedLocals": true,

    /* 
     関数で定義されたパラメータが、関数の本体内で一度も使用されていない場合にエラーまたは警告を出力します。
     不要な引数やタイプミスによる未使用パラメータを検出するのに役立ちます。
    */
    "noUnusedParameters": true,

    /* 
     関数内で、条件分岐などによって明示的な return ステートメントがない実行パスが存在し、かつ関数の返り値の型が void でない場合にエラーとします。
     関数の返り値が常に期待される型であることを保証します。
    */
    "noImplicitReturns": true,

    /* 
     switch 文の case 節の最後に break, return, throw などの制御フロー文がない場合にエラーとします（フォールスルーを許可しない）。
     意図しないフォールスルーによるバグを防ぐのに役立ちます。明示的にフォールスルーしたい場合は  falls through comment などを記述します。
    */
    "noFallthroughCasesInSwitch": true,

    /* 
     配列要素へのインデックスアクセス（arr[i]）やオブジェクトのプロパティへのアクセス（obj[key]）において、その要素/プロパティが undefined である可能性を型システムが考慮し、アクセス結果が undefined になりうる場合にエラーとします。
     これにより、実行時の undefined アクセスによるエラーを防ぎます。ただし、既存のコードベースでは多くのエラーが発生する可能性があるため、導入には注意が必要です。
    */
    "noUncheckedIndexedAccess": true,

    /* モジュール解決オプション (Module Resolution Options) */
    /*
     CommonJS モジュール (require()) と ES Modules (import) の間の相互運用性を高めるためのフラグです。
     これを true にすると、CommonJS モジュールを import 構文でインポートする際に、TypeScriptが互換性レイヤーを追加してくれます。
     例えば、`import * as React from 'react'` のように書けるようになります（一部のライブラリで必要）。
    */
    "esModuleInterop": true,

    /* 高度なオプション (Advanced Options) */
    /* 
     node_modules ディレクトリ内の型定義ファイル（.d.ts）の型チェックをスキップするかどうかを指定します。
     これを true にすると、ライブラリ自体の型定義に関するコンパイルエラーを無視するため、コンパイル時間を短縮できます。ただし、ライブラリ側の型定義に問題があっても気づきにくくなります。
    */
    "skipLibCheck": true,

    /* 
     import 文などでファイル名を指定する際に、ファイルシステムの大文字・小文字の区別を強制するかどうかを指定します。
     一部のOS（macOSなど）ではファイルシステムが大文字小文字を区別しませんが、Gitなどでは区別されるため、開発環境とデプロイ環境での不一致による問題を避けるために true にすることが推奨されます。
    */
    "forceConsistentCasingInFileNames": true,

    /*
     デコレーター機能の実験的なサポートを有効にするかどうかを指定します。
     デコレーターはTypeScriptの標準機能として採用されつつありますが、まだ提案段階の機能を利用する場合に true にします。フレームワーク（Angularなど）で使用されることが多いです。
    */
    "experimentalDecorators": true
  },

  /* コンパイル対象のファイル指定 (Include files) */
  /* 
   コンパイル対象に含めるファイルやディレクトリをGlobパターン（ワイルドカードを含むパス）で指定します。
   ここでは、プロジェクトルートの "./src" ディレクトリ以下全てと、"./test" ディレクトリ以下全てを含めることを指定しています。
   この設定がない場合、TypeScriptはデフォルトでカレントディレクトリとそのサブディレクトリにある全ての.ts, .d.ts, .tsxファイルをコンパイル対象とします。
  */
  "include": [
    "./src/**/*", // ./src ディレクトリ内の全てのファイルとサブディレクトリ
    "./test/**/*" // ./test ディレクトリ内の全てのファイルとサブディレクトリ
  ],

  /* コンパイル対象外のファイル指定 (Exclude files) */
  /* 
   コンパイル対象から除外するファイルやディレクトリをGlobパターンで指定します。
   include で指定したファイルや、デフォルトでコンパイル対象となるファイルの中から、除外したいものを指定します。
   一般的に、サードパーティライブラリがインストールされる "node_modules" ディレクトリや、自動生成される出力ディレクトリなどを除外します。
  */
  "exclude": [
    // npm/yarnなどでインストールされる依存ライブラリのディレクトリ。これらは通常、コンパイル済みか型定義ファイルのみが必要であり、自分でコンパイルする必要はありません。
    "node_modules",
    // AWS CDKなどのツールが生成する出力ディレクトリ。プロジェクトによって名前は異なります。
    "cdk.out"
    // その他、ビルドツールが生成するディレクトリ（例: "build", "dist" など、ただしoutDirと同じ場合は exclude しなくても outDir への出力で上書きされる）や、テスト用のモックファイルなど、コンパイル不要なファイルを指定します。
  ]
}
```

## 🎉 まとめ
実務だと既に誰かが作成した config ファイルを無意識的に使う形が多いかと思うので、あまり自分で触れることは案外ないです。

ですが、各設定の意味や用途についてイメージを掴むだけでも、TypeScript 開発への理解が深まったり設定を駆使することでチーム開発での生産性向上に役立てられます。

全てのプロジェクトで**使い回しではなく、プロジェクト毎で要件や開発スタイルに合わせて調整してみる**のも、良いかと思います。

## 💫 参考文献
* [tsconfig.jsonを設定する](https://typescriptbook.jp/reference/tsconfig/tsconfig.json-settings)
* [TSConfig Reference - Docs on every TSConfig option](https://www.typescriptlang.org/tsconfig/)