💬

tsconfig.jsonのよく使いそうなオプションを理解する

2021/10/30に公開

tsconfig.jsonを書く時に必要なオプションが何だったか、どんな役割を持つかを忘れてしまうため、個人的によく使いそうなオプションを書いていきます。

TypeScriptのバージョンは4.4です。

各オプション

target

TypeScriptはJavaScriptにコンパイルされるため、その時にどのバージョンのJavaScriptで出力するかをtargetで指定します。

ドキュメントを確認すると、デフォルトはES3ですが、以下の中からも選択できます。

es3, es5, es6/es2015, es2016, es2017, es2018, es2019, es2020, es2021, esnext

どれを選択すれば良いかは、Node.jsのバージョン毎に推奨されるtargetがあるため、node.greenを確認します。Node.jsのバージョンは、node -vで確認できます。

Name Supported Target 利用可能なAPI(一部)
Node 8 ES2017 Object.entries、Object.values、date.formatToParts
Node 10 ES2018 async iterables、promise.finally、rexexp.groups
Node 12 ES2019 array.flat、array.flatMap、string.trimStart
Node 14 ES2020 string.matchAll
Node 16 ES2021 string.replaceAll

tsconfig.jsonにtargetを指定する例

tsconfig.json
{
  "compilerOptions": {
    "target": "es2021"
  }
}

lib

targetに指定しているjsのバージョンには含まれていない、組み込みライブラリを使用する場合は、libに明示的な指定が必要になります。(使用しない場合は、書かなくても問題ありません)

指定可能なライブラリの一例は下記のとおりです。

ES5, ES6, ES2015, ES7, ES2016, ES2017, DOM, DOM.Iterable, WebWorker, ScriptHost, ES2015.Core, ES2015.Collection, ES2015.Generator, ES2015.Iterable, ES2015.Promise, ES2015.Proxy, ES2015.Reflect, ES2015.Symbol, ES2015.Symbol.WellKnown, ES2016.Array.Include, ES2017.object, ES2017.SharedMemory

これらの情報はTypeScript source codeで最新版を確認できます。

tsconfig.jsonにlibを指定する例

tsconfig.json
{
  "compilerOptions": {
    "target": "es2021",
    "lib": [
      "es2021",
      "esnext.promise",
      "esnext.weakref"
    ]
  }
}

module

出力されるJavaScriptが、どのようにモジュールを読み込むか指定します。バックエンドならcommonjs、フロントエンドならes2021esnextを指定すると良さそうです。

rootDir

コンパイル結果を出力する際に、どのディレクトリ配下を対象として出力するかを指定します。後述するincludeとは違い、コンパイル対象を決めるオプションではありません。

例えば設定を"rootDir": "./src"として、

tsconfig.json
{
  "compilerOptions": {
    "rootDir": "./src"
  }
}

ディレクトリの階層が以下のような時

├── src
│    └── hoge.ts
├── fuga.ts
└── tsconfig.json

hogeはsrc配下のため問題ないですが、fugaはsrc配下ではないためエラーとなります。

import hoge from './hoge'
import fuga from '../fuga'

moduleResolution

モジュールをどのように解決するのかを指定します。
指定する値は、NodeかClassicです。

以下のドキュメントを見ると、「かつてはTypeScriptのデフォルトの解決方法でした。現在では、この戦略は主に後方互換性のために存在しています」と書いてあるため、基本的にはnodeを指定すれば間違いないです。

https://www.typescriptlang.org/docs/handbook/module-resolution.html#classic

resolveJsonModule

trueを指定することで、JSONファイルから型の抽出や生成を行います。

sourceMap

trueを指定することで、出力されたJavaScriptファイルが実際に動作させるとき、デバッガーが元のTypeScriptソースファイルを表示できるようします。

outDir

以下のtsconfigの設定でyarn tscを実行すると、出力されたJavaScriptファイルは、distフォルダに生成されます。

tsconfig.jsonにoutDirを指定する例

tsconfig.json
{
  "compilerOptions": {
    "outDir": "./dist"
  }
}

yarn tscの実行

❯ yarn tsc
yarn run v1.22.11
$ /Users/hoge/test-project/node_modules/.bin/tsc
✨  Done in 3.42s.

treeコマンドでファイルの階層を確認する(例)

❯ tree dist
dist
├── index.js
└── index.js.map

importsNotUsedAsValues

importsNotUsedAsValues: "error"

interfaceなど型の定義だけを持つのファイルのインポートは、import typeでインポートしないと、コンパイルエラーにします。

// エラーになる
import { Ihoge } from "./Ihoge";

// エラーにならない
import type { Ihoge } from "./Ihoge";

forceConsistentCasingInFileNames

ファイルの文字列の大文字小文字を区別するかどうかを指定します。OSによっては、大文字小文字を区別出来ない場合があるため、trueにしておくと良さそうです。

ファイルが ./FileManager.ts を指定して fileManager.ts をインポートしようとした場合、ファイルは大文字と小文字を区別しないファイルシステムでは見つかりますが、大文字と小文字を区別するファイルシステムでは見つかりません。

https://www.typescriptlang.org/tsconfig#forceConsistentCasingInFileNames

strict

strictをtrueにすると、以下の各オプションがすべてtrueになります。デフォルト値はすべてfalseのため、trueにした場合の挙動は次のとおりです。

オプション 説明
alwaysStrict strict modeで解釈し、出力されるJavaScriptファイルにもuse strictを追加する
strictNullChecks nullやundefinedを代入したい場合、明示的に指定しないといけなくなる
strictBindCallApply 歴史的経緯により正しく型付けされていなかった、Functionのbind(),call(),apply()メソッドを厳格に型付けする
strictFunctionTypes 歴史的経緯により存在した、Function型の誤った型変換が許されなくなる
strictPropertyInitialization コンストラクタ内でundefinedが許されないプロパティが、全て代入されているかどうかチェックされる
noImplicitAny 型が推論不能のときにコンパイルエラーにする
noImplicitThis thisの型が推論不能のときコンパイルエラーにする
useUnknownInCatchVariables catchの例外変数のデフォルトの型がunknownになる

https://www.typescriptlang.org/tsconfig#strict

noImplicitReturns

関数の戻り値がvoid以外のときにreturnを必須にします。

noFallthroughCasesInSwitch

switch文で、caseをbreakやreturnで終えていることを必須にします。

noUncheckedIndexedAccess

インデックス型や配列で宣言されたオブジェクトが持つプロパティへのアクセスを厳密に評価します。まず、noUncheckedIndexedAccessがfalseの場合は、以下のコードを書いてもエラーになりません。変数resultがundefinedで出力されます。

type Props = {
  [key: string]: string 
}

const run = (props: Props) => {
  const result: string = props.mouse
  console.log(result) // undefined
}

const animal: Props = {
  cat: "Meow",
  dog: "Bowwow"
}

run(animal)

noUncheckedIndexedAccessをtrueにすることで、Type 'string | undefined' is not assignable to type 'string'. Type 'undefined' is not assignable to type 'string'.(2322)とエラーを出してくれます。

noImplicitOverride

スーパークラスのメソッドをオーバーライドする時、overrideを必須にします。

include

コンパイルする対象ファイルを記述します。

src/**/*と指定した場合、src配下のファイル全て(ディレクトリのネストが深くなっても再帰的に全て)がコンパイル対象になります。

includeの指定にファイルの拡張子が含まれていない場合、デフォルトでは.ts .tsx .d.ts、allowJsがtrueの場合は.js .jsxが含まれます。

tsconfig.jsonにincludeを指定する例(includeはcompilerOptionsと同じく、1つめの階層で宣言します)

tsconfig.json
{
  "compilerOptions": {
   // 省略
  },
  "include": ["src/**/*"]
}

https://www.typescriptlang.org/tsconfig#include

完成形

Node.jsのプロジェクトで使いたかったため、今回は"module": "commonjs",を指定しています。

tsconfig.json
{
  "compilerOptions": {
    "target": "es2021",
    "module": "commonjs",
    "rootDir": "./src",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "sourceMap": true,
    "outDir": "./dist",
    "importsNotUsedAsValues": "error",
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "noUncheckedIndexedAccess": true,
    "noPropertyAccessFromIndexSignature": true
  },
  "include": ["src/**/*"]
}

所感

TypeScript: TSConfig ReferenceのType Checkingにある項目は、よく利用するので特に目を通しておいた方が良いです。

ドキュメントから引用すると、以下のオプションたちです。

allowUnreachableCode,allowUnusedLabels,alwaysStrict,exactOptionalPropertyTypes,noFallthroughCasesInSwitch,noImplicitAny,noImplicitOverride,noImplicitReturns,noImplicitThis,noPropertyAccessFromIndexSignature,noUncheckedIndexedAccess,noUnusedLocals,noUnusedParameters,strict,strictBindCallApply,strictFunctionTypes,strictNullChecks,strictPropertyInitialization anduseUnknownInCatchVariables

参考

https://www.typescriptlang.org/ja/tsconfig
https://book.yyts.org/reference/tsconfig/tsconfig.json-settings
https://qiita.com/ryokkkke/items/390647a7c26933940470#include
https://eh-career.com/engineerhub/entry/2021/08/26/110000

Discussion