なんとなく使うtsconfig.jsonをやめる
なんとなく使ってませんか?
TypeScript を使っているとtsconfig.jsonというファイルをよく見かけますよね。
とはいえ、内容はよくわからないまま、
- とりあえず
tsc --initで作ったやつそのまま - 参考記事の設定内容をコピペするだけ
 
になってませんか?
私はなってます...。
ということで、自分の勉強+同じような方の参考になればと思いこの記事を書くことにしました。
tsconfig.json の基本的な考え方から、最低限押さえておきたい設定項目をまとめていきます。
🔧 tsconfig.json は何をするファイル?
Node.jsはそれ自身ではTypeScriptをサポートしているわけではないため、TypeScriptの導入をする時はTypeScriptの設定ファイルであるtsconfig.jsonが必要です。
つまり、Node.jsは.tsファイル(TypeScript)を直接実行できません(TypeScript をネイティブにサポートしていない)。
したがって.ts→.jsに変換(=コンパイル)する必要があります。
その変換ルールを記述するのがtsconfig.jsonです!
tsconfig.jsonの役割
- TypeScript に「どのファイルを対象にして、どんなルールで JavaScript に変換するか」を指示する
 - 型チェックや出力形式など、プロジェクト全体の TypeScript 設定の中核
 - tsc(TypeScript コンパイラ)がこの設定に従って動作する
 
最低限押さえておきたい設定項目
{
  "include": [
    "src/**/*"
  ],
  "exclude": [
    "node_modules",
    "dist"           
  ],
  "compilerOptions": {
    "target": "ES2020", 
    "module": "ESNext", 
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true, 
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "sourceMap": true,
    "baseUrl": "./",
    "paths": {
      "@/*": ["src/*"]
    },
    "moduleResolution": "node",
  }
}
このテンプレートに沿って詳しく見ていきます。
include
コンパイル対象とするファイルやフォルダを指定します(ワイルドカード使用可)。
exclude
コンパイルから除外するファイルやフォルダを指定します(ワイルドカード使用可)。
注意▼
重要: excludeはincludeの結果として、どのファイルが含まれるべきかのみに影響を与えます。 excludeに指定されたファイルは、コードでのimportやtypesでのインクルード、/// <reference ディレクティブ、filesリストの指定によって、コードベースの一部となり得ます。
excludeはコードベースに含まれているファイルの読み込みを防ぐための仕組みではありません。include設定の結果を変更するだけです。
と公式ドキュメントに記載があるように、excludeに指定したファイルでも、includeに指定したファイル内でimportしていればコンパイル対象になります。
compilerOptions
target
どのバージョンの JavaScript に変換するかを指定します。
出力する JavaScript の対応環境(ブラウザやNode.jsのバージョン)に合わせるために必要です。
モダン構文を使いたいならES2020やESNext、古い環境向けならES5。
module
出力する JavaScript のモジュール形式を指定します。
TypeScript の import/export を、どんな形式で JavaScript に変換するかを決めるオプションです。
ESNext、CommonJS、ES6など、Node.jsやブラウザでの使い方に応じて選びます。
outDir
変換後の.jsファイルを出力するディレクトリを指定します。
※通常はdistやbuildに設定
rootDir
コンパイル元の TypeScript ファイル群が存在するディレクトリを指定します。
srcに指定することで、src→distのようにフォルダ構造を保てます。
strict
trueを指定することで、TypeScript の厳格な型チェックモードを一括で有効にできます。
※バグを未然に防ぎやすくなるため、基本的にtrue推奨
esModuleInterop
trueを指定することで、CommonJSをimportで自然に書けるようになります。
CommonJSを使っている(または混在している)環境で有効です。
※特にimport React from 'react'のような構文を使う際に必須
skipLibCheck
trueを指定することで、node_modules内の型定義ファイル(.d.ts)のチェックをスキップするようになります。
主な目的は、ビルドの高速化・安定化ですが、型エラーが出るライブラリへの一時的な対応策として使われることもあります。
- 型定義が雑な古いライブラリを使っていて、勝手にエラーが出る
 - 自分のコードには関係ないのに、ライブラリの型定義でコンパイルが止まる
 - ビルドが遅くなる
 
のようなときに有効です。
forceConsistentCasingInFileNames
trueを指定することで、ファイル名の大文字・小文字の違いをチェックします。
OS による差が原因のバグを防げます。
バグの例として、以下のような場合があります。
  // 実際のファイル名は './utils/math.ts'
  import { add } from './Utils/math'; // ❌ 実は "U" が大文字になっている
windows の場合▼
ファイルシステムが大文字・小文字を区別しない(≒これでも動く)
Linux(本番サーバーなど)の場合▼
大文字・小文字を区別するため、動かない! → 実行時エラーになる
sourceMap
trueを指定することで、TypeScript の元コードと出力された JavaScript の対応関係を記録します。
ブラウザやNode.jsのデバッガで、元の TypeScript ソースでデバッグできるようになります。
baseUrl
モジュールのルートパスを指定します。
これを指定すると、任意のフォルダからの絶対パスでインポートすることができます。
paths
baseUrlで基準となるフォルダを決めた上で、pathsで短い名前(エイリアス)を作れます。
例えば、下記のような設定があった場合、@/utilsと書くと、実際にはsrc/utilsを指すようになります。
  "paths": {
    "@/*": ["src/*"]
  }
moduleResolution
モジュールをimportしたときに、どのようにファイルを探すか(解決するか)を指定できます。
例えば、nodeを指定すると、TypeScript は Node.js と同じルールでモジュールを探します。
具体的には、下記のような動作になります。
- 
importで指定されたパスがファイル名と一致しない(拡張子が省略されている)場合でも、.ts、.js、.d.tsなどの拡張子を補完して探してくれる - 
node_modulesフォルダ内のライブラリも自動的に探索対象になる 
最後に
tsconfig.jsonについて、これまで設定内容をよくわからないまま使っていたので、改めて概要と最低限押さえておきたい項目をまとめてみました。
基本を理解しておくだけでも、「何が必要で何が不要か」を判断できるようになってくるのかなと思います。
今回は最低限に絞って紹介しましたが、他にも知っておくと便利な設定はたくさんあります。
今後はもう少し踏み込んだ内容の記事にも挑戦していこうと思っています。
少しでもなんとなくを減らして、日々の開発体験をもっと快適にしていきましょう!
参考
Discussion