tsconfig.jsonの主要オプションを理解する

# 概要

社内勉強会の資料。
TypeScriptの`tsconfig.json`にはオプションが色々とあるので、それらの意味や用途を理解する目的です。

tscのバージョンは`3.7.2`を使用します。
VSCodeのバージョンは`1.40.1`を使用します。

公式のドキュメント：https://www.typescriptlang.org/docs/handbook/tsconfig-json.html

公式ドキュメントの和訳：http://js.studio-kingdom.com/typescript/project_configuration/tsconfig_json

また、各項目の詳しい説明はdetailsタグを使ってデフォルトで非表示にしています（全部デフォルトで表示するとめっちゃ長いので）。「詳しく」の部分をクリックすると展開されます。

**2020年5月24日追記**
公式のtsconfig.jsonのドキュメントがめっちゃ綺麗になったので、まずはこっち見た方が良いです！
https://www.typescriptlang.org/tsconfig

# 準備

`typescript`をインストールして、`tsc --init`する。

```console
$ mkdir tsconfig; cd tsconfig
$ npm init
$ npm install --save-dev typescript
$ npx tsc -v
Version 3.7.2
$ npx tsc --init
message TS6071: Successfully created a tsconfig.json file.
$ ls -1
node_modules
package-lock.json
package.json
tsconfig.json
$ cat tsconfig.json
```

<details><summary>`init`直後の`tsconfig.json`を表示（長い）</summary><div>

```json
{
  "compilerOptions": {
    /* Basic Options */
    // "incremental": true,                   /* Enable incremental compilation */
    "target": "es5",                          /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
    "module": "commonjs",                     /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
    // "lib": [],                             /* Specify library files to be included in the compilation. */
    // "allowJs": true,                       /* Allow javascript files to be compiled. */
    // "checkJs": true,                       /* Report errors in .js files. */
    // "jsx": "preserve",                     /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
    // "declaration": true,                   /* Generates corresponding '.d.ts' file. */
    // "declarationMap": true,                /* Generates a sourcemap for each corresponding '.d.ts' file. */
    // "sourceMap": true,                     /* Generates corresponding '.map' file. */
    // "outFile": "./",                       /* Concatenate and emit output to single file. */
    // "outDir": "./",                        /* Redirect output structure to the directory. */
    // "rootDir": "./",                       /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
    // "composite": true,                     /* Enable project compilation */
    // "tsBuildInfoFile": "./",               /* Specify file to store incremental compilation information */
    // "removeComments": true,                /* Do not emit comments to output. */
    // "noEmit": true,                        /* Do not emit outputs. */
    // "importHelpers": true,                 /* Import emit helpers from 'tslib'. */
    // "downlevelIteration": true,            /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
    // "isolatedModules": true,               /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */

    /* Strict Type-Checking Options */
    "strict": true,                           /* Enable all strict type-checking options. */
    // "noImplicitAny": true,                 /* Raise error on expressions and declarations with an implied 'any' type. */
    // "strictNullChecks": true,              /* Enable strict null checks. */
    // "strictFunctionTypes": true,           /* Enable strict checking of function types. */
    // "strictBindCallApply": true,           /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
    // "strictPropertyInitialization": true,  /* Enable strict checking of property initialization in classes. */
    // "noImplicitThis": true,                /* Raise error on 'this' expressions with an implied 'any' type. */
    // "alwaysStrict": true,                  /* Parse in strict mode and emit "use strict" for each source file. */

    /* Additional Checks */
    // "noUnusedLocals": true,                /* Report errors on unused locals. */
    // "noUnusedParameters": true,            /* Report errors on unused parameters. */
    // "noImplicitReturns": true,             /* Report error when not all code paths in function return a value. */
    // "noFallthroughCasesInSwitch": true,    /* Report errors for fallthrough cases in switch statement. */

    /* Module Resolution Options */
    // "moduleResolution": "node",            /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
    // "baseUrl": "./",                       /* Base directory to resolve non-absolute module names. */
    // "paths": {},                           /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
    // "rootDirs": [],                        /* List of root folders whose combined content represents the structure of the project at runtime. */
    // "typeRoots": [],                       /* List of folders to include type definitions from. */
    // "types": [],                           /* Type declaration files to be included in compilation. */
    // "allowSyntheticDefaultImports": true,  /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
    "esModuleInterop": true,                  /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
    // "preserveSymlinks": true,              /* Do not resolve the real path of symlinks. */
    // "allowUmdGlobalAccess": true,          /* Allow accessing UMD globals from modules. */

    /* Source Map Options */
    // "sourceRoot": "",                      /* Specify the location where debugger should locate TypeScript files instead of source locations. */
    // "mapRoot": "",                         /* Specify the location where debugger should locate map files instead of generated locations. */
    // "inlineSourceMap": true,               /* Emit a single file with source maps instead of having a separate file. */
    // "inlineSources": true,                 /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */

    /* Experimental Options */
    // "experimentalDecorators": true,        /* Enables experimental support for ES7 decorators. */
    // "emitDecoratorMetadata": true,         /* Enables experimental support for emitting type metadata for decorators. */

    /* Advanced Options */
    "forceConsistentCasingInFileNames": true  /* Disallow inconsistently-cased references to the same file. */
  }
}

```

</div></details>

ここにあらかたの説明は書かれている。が、正直この説明だけでは何のことやらわからないので、一つずつ見ていく。

ちなみに、VSCodeを使っている場合は、使用できるオプション名やその値は補完が効くので便利。

# 第一階層

## compilerOptions

```json
"compilerOptions": {}
```

コンパイルする際のオプション。基本的にここにオプションを書いていく。

## files

```json
"files": [
  "core.ts",
  "sys.ts",
  "types.ts",
]
```

コンパイルするファイルを直接指定する。
こちらは`include`や`exclude`と違ってワイルドカードを使用できない。
拡張子は省略可能。省略した場合、`.ts`ファイルが優先して対象になる（`hoge.ts`と`hoge.tsx`がある際に`"hoge"`を指定すると`.ts`ファイルだけがコンパイルされる）。

## include

コンパイルする対象ファイルを記述する。
ワイルドカード（`*`,`?`,`**/`）が使える。

> - \* 0個以上の文字に一致します（ディレクトリ区切り文字を除く）
> - ? 任意の1文字に一致します（ディレクトリ区切り文字を除く）
> - **/ 任意のサブディレクトリに再帰的に一致します

```json
"include": [
  "src/**/*"
]
```

上記の場合は、src配下のファイル全て（ディレクトリのネストが深くなっても再帰的に全て）がコンパイル対象。

拡張子を指定しない（`*`のみ）、もしくは拡張子にアスタリスクを使用する（`hoge.*`）場合、デフォルトでは下記の拡張子のファイルのみが対象になる。

- `.ts`
- `.tsx`
- `.d.ts`

ただし、`compilerOptions.allowJs`が`true`の場合は、下記の拡張子も含む。

- `.js`
- `.jsx`

`files`も`include`も指定しない場合、`tsconfig.json`が置かれているディレクトリ配下の全てのTypeScriptファイル（拡張子が`.ts`、`.d.ts`、`.tsx`であるファイル）のうち、`exclude`に含まれるファイル以外がコンパイル対象になる。

## exclude

`include` で指定したファイルから特別に除外するファイルを記述する。
`include`と同じワイルドカードが使える。

（2022/04/02）公式のドキュメントでも強調されているのですが、この `exclude` は **「指定したファイルを tsc が読み込まないようにする」オプションではありません。** あくまでも、 `include` で指定したファイルの中から除外するファイルを指定するだけです。つまり、エントリーファイルから exclude するだけで、エントリーした後のファイルには関知しません。
なので、例えば `exclude` に `hoge.ts` を指定しても、 `include` に含まれている `piyo.ts` が `hoge.ts` を `import` していれば tsc は `hoge.ts` を読み込みます。
下記ドキュメントをご確認ください。

https://www.typescriptlang.org/ja/tsconfig#exclude

`exclude`は指定しない場合デフォルトで以下の値を含む。

- `node_modules`
- `bower_components`
- `jspm_packages`
- `outDir`オプションで指定しているディレクトリ配下のファイル

逆に言うと、`tsconfig.json`に`exclude`オプションが指定されている場合は、`outDir`の中身も対象になってしまう。
<details><summary>詳しく</summary><div>

```tsconfig.json
"outDir": "./dist"

"exclude": ["node_modules"]
```

```console
$ ls -1 dist
piyo.ts
```

となっているとしましょう。

そのまま `tsc` コマンドを叩くと、この場合`exclude`が明示的に指定されているため、`outDir`の中身はexcludeの対象になりません。
そのため、アウトプットはこうなります。

```
dist/
├── dist
│   └── piyo.js
└── piyo.ts
```

ややこしいですが、一つ目の`dist`ディレクトリは`outDir`で指定したディレクトリです。つまり、`dist`ディレクトリもコンパイル対象になっているため、`dist/piyo.ts`をコンパイルしたアウトプットである`dist/piyo.js`が、`outDir`で指定されている`dist`ディレクトリに入ってしまっています。

まあ、`outDir`に指定しているディレクトリにコンパイル前のファイルを入れることは基本無いと思います。

</div></details>


## filesとincludeとexcludeの適用順番

簡単に言うとfilesが最強、include < exclude。

**`include`で指定されたファイルは`exclude`で除外されるが、`files`に指定したファイルは`exclude`に関係なく問答無用でコンパイル対象になる。**

また、このルールによってコンパイル対象になったファイルが参照するファイルもコンパイル対象に含まれる。

## extends

`tsconfig.json`は複数のファイルに分割することができ、この`extend`でファイルパスを指定することで、その`tsconfig.json`が継承する`tsconfig.json`ファイルを指定できる。子は親の設定を上書きする。

```json
"extends": "./configs/base"
```

テストだけ設定を変えるなど、環境ごとの出力の違いに対応する場面などで使う。

## compileOnSave

この値を`true`にすると、`tsconfig.json`を保存した際にコンパイルが走るようになる。

> This feature is currently supported in Visual Studio 2015 with TypeScript 1.8.4 and above, and atom-typescript plugin.

とのことなので、これを満たしていれば使える。
役に立つんだろうか、これ...

## references

```json
"references": [
  { "path": "../src" }
]
```

[Project References](https://www.typescriptlang.org/docs/handbook/project-references.html)を有効にする際に使用する。
`path`にはこの`tsconfig.json`が存在するディレクトリから参照する別の`tsconfig.json`が存在するディレクトリパス、またはその別の`tsconfig.json`のパスを指定する。
後述の`compilerOptions.composite`と組み合わせて使う。

Project Referencesに関しては説明に時間がかかるので一旦省略。
上記の公式ドキュメント読むとわかります。

# compilerOptions

## target

```json
"target": "es5"
```

> Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'.

どのバージョンでjsを出力するか。
つまりデフォルトの`ES3`であれば、コンパイルの結果出力されるjsはES3に準拠しているjsコードということになる。

<details><summary>詳しく</summary><div>

```tsconfig.json
"target": "es3"
```

```index.ts
const func = async () => {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve("5秒経ちました");
    }, 5000);
  });
};
```

だとしましょう。
これをコンパイルした結果はこちら。

<details><summary>コンパイル結果</summary><div>

```index.js
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __generator = (this && this.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (_) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};
var func = function () { return __awaiter(void 0, void 0, void 0, function () {
    return __generator(this, function (_a) {
        return [2 /*return*/, new Promise(function (resolve) {
                setTimeout(function () {
                    resolve("5秒経ちました");
                }, 5000);
            })];
    });
}); };

```

</div></details>

そして次は`target`を`"target": "es2019"`にしてコンパイルした結果がこちら。

<details><summary>コンパイル結果</summary><div>

```index.js
"use strict";
const func = async () => {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve("5秒経ちました");
        }, 5000);
    });
};
```

</div></details>

これはつまり、`es3`に準拠させようとするとasyncやPromiseなんて存在しないので、レガシーなjsコードでPromiseやasyncを再現するPolyfilが手前で生成されていて、それを使用して元のコードを再現している、そして`es2019`に準拠させる場合は、asyncやPromiseはすでに標準で組み込まれているので、そのまま出力されるということです。

ここはTypeScriptのコンパイルというよりはBabel的な役割ですね。

</div></details>

## lib

```json
"lib": ["dom", "es2019"]
```

> Specify library files to be included in the compilation.

コンパイルする際に使用する組み込みライブラリを指定する。

基本的には`target`で指定しているjsのバージョンに含まれているものは暗黙的に指定される。
ただし、`target`に指定しているjsのバージョンには含まれていない組み込みライブラリを使用する場合は、明示的な指定が必要。

<details><summary>詳しく</summary><div>

例えば、`tsconfig.json`で`target`を指定しない場合、デフォルトでは`ES3`になるため、ES3に含まれていない組み込みライブラリはエラーになる。

```index.ts
const func = async () => {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve("5秒経ちました");
    }, 5000);
  });
};
```

```console
index.ts:2:14 - error TS2585: 'Promise' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later.

2   return new Promise(resolve => {
               ~~~~~~~
```

（asyncは組み込みライブラリではなく記法なのでこの場合は関係なし）

こういう場合は、`lib`に

```tsconfig.json
"lib": ["dom", "es2015"]
```

と指定することでエラーを回避できる。

ちなみに、明示的に指定すると暗黙的に指定されていたものが指定されなくなるので、必要なものは全て列挙する必要がある。
この場合、`setTimeout`を使っていて、こういったブラウザで提供されるライブラリを使用するには`"dom"`を指定する必要がある。
（つまり`lib`を指定していない場合は`dom`も暗黙的に指定されている）

</div></details>

## module

```
module: "esnext"
```

> Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'.

デフォルト値は下記。

```
target === "ES3" or "ES5" ? "CommonJS" : "ES6"
```

出力するjsのモジュールの仕組みとして何を使用するかを指定する。

<details><summary>詳しく</summary><div>

```index.ts
export const func = async () => {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve("5秒経ちました");
    }, 5000);
  });
};
```

```tsconfig.json
"module": "commonjs"
```

の場合、コンパイル結果は

```index.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.func = async () => {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve("5秒経ちました");
        }, 5000);
    });
};
```

```tsconfig.json
"module": "es2015"
```

の場合、コンパイル結果は

```index.js
export const func = async () => {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve("5秒経ちました");
        }, 5000);
    });
};
```

</div></details>

## outDir

```
"outDir": "./dist"
```

> Redirect output structure to the directory.

何も指定しない場合、コンパイルされたjsはコンパイルしたtsファイルと同じディレクトリに作成される。
このオプションでディレクトリを指定した場合、tsファイルのディレクトリ構成をそのままに保ちつつ、指定したディレクトリにjsファイルを作成する。

<details><summary>詳しく</summary><div>

```
.
├── index.ts
├── package-lock.json
├── package.json
├── src
│   ├── hoge.ts
│   └── piyo
│       ├── foo
│       │   └── foo.ts
│       └── piyo.ts
└── tsconfig.json
```

こういうディレクトリ構成だった場合、何も指定しない場合は

```
.
├── index.js
├── index.ts
├── package-lock.json
├── package.json
├── src
│   ├── hoge.js
│   ├── hoge.ts
│   └── piyo
│       ├── foo
│       │   ├── foo.js
│       │   └── foo.ts
│       ├── piyo.js
│       └── piyo.ts
└── tsconfig.json
```

こうなる。

`"outDir": "./dist"`を指定すると

```
.
├── dist
│   ├── index.js
│   └── src
│       ├── hoge.js
│       └── piyo
│           ├── foo
│           │   └── foo.js
│           └── piyo.js
├── index.ts
├── package-lock.json
├── package.json
├── src
│   ├── hoge.ts
│   └── piyo
│       ├── foo
│       │   └── foo.ts
│       └── piyo.ts
└── tsconfig.json
```

こうなる。

ディレクトリ構成を保ちつつ指定した`dist`ディレクトリにjsファイルが作成されている。

</div></details>

## allowJs

```json
"allowJs": true
```

> Allow javascript files to be compiled.

これをtrueにしておくと、`.js`と`.jsx`もコンパイル対象に含まれるようになる。
部分的にjsで書いている場合などにtrueにする。
tsでは無いので型チェックなどは行われないが、tschsjsのトランスパイル（ここではロジックの変更なしで記法を指定バージョンに準拠させる変換の意）なども行うので、その対象となる。

こちらの記事がわかりやすいです！
[TypeScriptを徐々に導入する - Qiita](https://qiita.com/pirosikick/items/183987f8fb79f573ec8b)

## checkJs

```json
"checkJs": true
```

> Report errors in .js files.

allowJsの上記の記事のコメントで会話されているように、JSDocを使うことでjsファイルの型チェックを行うオプションです。
[Type Checking JavaScript Files - github.com/Microsoft/TypeScript](https://github.com/Microsoft/TypeScript/wiki/Type-Checking-JavaScript-Files)

tsで書き直すことは出来ないけど、型チェックの恩恵を受けたいみたいな場合に、JSDocの追加だけなら許容できる（コメントの追加であってコードの変更じゃないから）みたいな場面があるんでしょうか。

## jsx

```json
"jsx": "preserve"
```

> Specify JSX code generation: 'preserve', 'react-native', or 'react'.

tsxファイルをjsxやjsにコンパイルする際の出力の形式を指定する。

<details><summary>詳しく</summary><div>

まずは`preserve`

```tsconfig.json
"jsx": "preserve"
```

```component.tsx
declare namespace JSX {
  interface IntrinsicElements {
    section: any;
    h1: any;
    p: any;
  }
}

const Component = () => (
  <section>
    <h1>Component</h1>
    <p>Contents</p>
  </section>
);
```

（jsxの型についてはこちらの記事がわかりやすいです！[TypeScriptの型におけるJSXサポートが100%分かる記事 - Qiita](https://qiita.com/uhyo/items/adf6cb83333a25097f25)）

の場合は

```component.jsx
"use strict";
var Component = function () { return (<section>
    <h1>Component</h1>
    <p>Contents</p>
  </section>); };

```

こうなる。`preserve`はjsxをjsxのまま保持するので、拡張子は`.jsx`になる。
jsxのコンパイルをtscではなくBabelなど他に任せたい場合に使用する。

Reactのコードにコンパイルしたい場合は下記のように`"react"`を指定する。

```tsconfig.json
"jsx": "react"
```

とりあえずコンパイルだけなので`@types/react`だけインストール。

```console
$ npm install --save-dev @types/react
```

```component.ts
const Component = () => (
  <section>
    <h1>Component</h1>
    <p>Contents</p>
  </section>
);
```

`@types/react`がインストールされていればjsxの型についてこちらが書く必要は無いのでこれだけ:arrow_up:。

```component.js
"use strict";
var Component = function () { return (React.createElement("section", null,
    React.createElement("h1", null, "Component"),
    React.createElement("p", null, "Contents"))); };
```

結果はこれ:arrow_up:。jsxの記法が完全に消え、拡張子も`.js`になる。


```tsconfig.json
"jsx": "react-native"
```

`react-native`は使う予定が無いので一旦パス。

</div></details>

## declaration

```json
"declaration": true
```

> Generates corresponding '.d.ts' file.

これを`true`にすると、コンパイルしたtsファイルの中で`export`しているもの全ての型定義ファイルをファイルごとに作成する。
`export`が一つもなくてもファイル自体は作成される。

<details><summary>詳しく</summary><div>

```tsconfig.json
"declaration": true
```

```
.
├── index.ts
├── package-lock.json
├── package.json
├── src
│   ├── hoge.ts
│   └── piyo
│       ├── foo
│       │   └── foo.ts
│       └── piyo.ts
└── tsconfig.json
```

こういうディレクトリ構成だとして、`index.ts`は、

```index.ts
console.log("hoge");

export const func = async () => {
  // Promiseにジェネリクスで型を渡さないと`resolve`の返り値が`unknown`になるので`string`渡す
  return new Promise<string>(resolve => {
    setTimeout(() => {
      resolve("5秒経ちました");
    }, 5000);
  });
};

const hoge = "hoge";
```

で、その他の`.ts`ファイルは空ファイル。

この状態でコンパイル結果は下記（`"outDir": "./dist"`で、`./dist`配下だけ表示）。

```
./dist/
├── index.d.ts
├── index.js
└── src
    ├── hoge.d.ts
    ├── hoge.js
    └── piyo
        ├── foo
        │   ├── foo.d.ts
        │   └── foo.js
        ├── piyo.d.ts
        └── piyo.js
```

```index.d.ts
export declare const func: () => Promise<string>;
```

`index.js`のうち、`func`の型定義が出力されている。

試しに`index.ts`の`const hoge = ~~~`を`export`してからコンパイルすると、

```index.ts
console.log("hoge");

export const func = async () => {
  return new Promise<string>(resolve => {
    setTimeout(() => {
      resolve("5秒経ちました");
    }, 5000);
  });
};

export const hoge = "hoge";
```

結果は下記。

```index.d.ts
export declare const func: () => Promise<string>;
export declare const hoge = "hoge";
```

`export`すれば型定義ファイルの出力対象になる。

空ファイルの型定義ファイルは空ファイルになる:arrow_down:。

```piyo.d.ts
```

</div></details>

## declarationMap

```
"declarationMap": true
```

> Generates a sourcemap for each corresponding '.d.ts' file.

`declaration`オプションと併用するオプション。
これを`true`にすると、型定義のmapファイルが作成される（型定義ファイル自体にも、mapファイルの居場所が追記される）。
型定義のmapファイルというのは拡張子`.d.ts.map`を持つファイルで、このmapファイルがあると、**エディタで定義元にジャンプ（`cmd + click`など）した際に、型定義ファイルではなく実際のtsコードに飛ぶことができる。**

<details><summary>詳しく</summary><div>

まず、最初に`"declarationMap": false`な状態で、コンパイルする。

```tsconfig.json
"declaration": true,
"declarationMap": false,
```

そして、新しく適当なtsファイルを作成し、今コンパイルした`func`関数を`import`する。

```hoge.ts
import { func } from "./dist/index";

func();
```

<img width="545" alt="スクリーンショット 2019-11-23 21.08.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132179/753c2e05-feeb-95a7-e023-6bcf605d8bca.png">

その状態で`func`を`cmd + click`すると、

<img width="458" alt="スクリーンショット 2019-11-23 21.08.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132179/857bc0e9-a273-4a11-ebf2-6872e05bd783.png">

ここ、つまり型定義ファイル（`index.d.ts`）に飛ぶ。

次に、`"declarationMap": true`で再度コンパイル（`hoge.ts`はコンパイルに含めず）。

```tsconfig.json
"declaration": true,
"declarationMap": true,
```

```index.d.ts
export declare const func: () => Promise<string>;
export declare const hoge = "hoge";
//# sourceMappingURL=index.d.ts.map
```

```index.d.ts.map
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,IAAI,uBAMhB,CAAC;AAEF,eAAO,MAAM,IAAI,SAAS,CAAC"}
```

結果は上記のように、型定義ファイルにmapファイルのパスのコメントが追加され、mapファイルも作成される。

この状態で、先ほどの`hoge.ts`の`func`を`cmd + click`すると

<img width="400" alt="スクリーンショット 2019-11-23 21.12.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132179/efaf3230-9a44-0025-ddcb-cdd7a23fa39a.png">

ここ、つまり型定義ファイルではなく、実際のtsコードに飛ぶ。

</div></details>

## sourceMap

```
"sourceMap": true
```

> Generates corresponding '.map' file.

こちらは型定義ではなく、jsのmapファイル。

参考： https://developer.mozilla.org/ja/docs/Tools/Debugger/How_to/Use_a_source_map

<details><summary>詳しく</summary><div>

`true`してコンパイル（`"target": "es2019"`）した結果は下記。

```index.js
console.log("hoge");
export const func = async () => {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve("5秒経ちました");
    }, 5000);
  });
};
export const hoge = "hoge";
//# sourceMappingURL=index.js.map
```

```index.js.map
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AAEpB,MAAM,CAAC,MAAM,IAAI,GAAG,KAAK,IAAI,EAAE;IAC7B,OAAO,IAAI,OAAO,CAAS,OAAO,CAAC,EAAE;QACnC,UAAU,CAAC,GAAG,EAAE;YACd,OAAO,CAAC,SAAS,CAAC,CAAC;QACrB,CAAC,EAAE,IAAI,CAAC,CAAC;IACX,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,IAAI,GAAG,MAAM,CAAC"}
```

</div></details>

## outFile

```json
"outFile": "./dist/bundle.js"
```

> Concatenate and emit output to single file.

これを`true`にすると、コンパイル結果を一つのファイルにまとめる。
バンドラ的機能。
ただし、これを使用するには、`module`オプションが`amd`または`system`である必要がある。
`outFile`を指定した場合は`outDir`オプションは無視される。

<details><summary>詳しく</summary><div>

まずは、`"target": "es2019"`でかつ`"module"`は未指定（`targte`が`es2019`なので`module`の値はデフォルト値の`es6`）でコンパイル。

```tsconfig.json
"target": "es2019",
"outFile": "./dist/bundle.js"
```

```console
index.ts:3:1 - error TS6131: Cannot compile modules using option 'outFile' unless the '--module' flag is 'amd' or 'system'.
```

`amd`か`system`にしろと怒られる。

次は、`module`を`amd`にしてコンパイル。

```tsconfig.json
"target": "es2019",
"module": "amd",
"outFile": "./dist/bundle.js"
```

```index.ts
import { hoge } from "./src/hoge";

export const func = async () => {
  return new Promise<string>(resolve => {
    setTimeout(() => {
      resolve("5秒経ちました");
    }, 5000);
  });
};

console.log(hoge);
```

参考のために`./src/hoge.ts`を`index.ts`から`import`。

```src/hoge.ts
export const hoge: string = "HOGE";
```

結果は下記。

```./dist/bundle.js
"use strict";
define("src/hoge", ["require", "exports"], function (require, exports) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    exports.hoge = "HOGE";
});
define("index", ["require", "exports", "src/hoge"], function (require, exports, hoge_1) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    exports.func = async () => {
        return new Promise(resolve => {
            setTimeout(() => {
                resolve("5秒経ちました");
            }, 5000);
        });
    };
    console.log(hoge_1.hoge);
});
```

次は、`module`を`system`にして同じコードをコンパイル。

```tsconfig.json
"target": "es2019",
"module": "system",
"outFile": "./dist/bundle.js"
```

結果は下記。

```bundle.js
"use strict";
System.register("src/hoge", [], function (exports_1, context_1) {
    "use strict";
    var hoge;
    var __moduleName = context_1 && context_1.id;
    return {
        setters: [],
        execute: function () {
            exports_1("hoge", hoge = "HOGE");
        }
    };
});
System.register("index", ["src/hoge"], function (exports_2, context_2) {
    "use strict";
    var hoge_1, func;
    var __moduleName = context_2 && context_2.id;
    return {
        setters: [
            function (hoge_1_1) {
                hoge_1 = hoge_1_1;
            }
        ],
        execute: function () {
            exports_2("func", func = async () => {
                return new Promise(resolve => {
                    setTimeout(() => {
                        resolve("5秒経ちました");
                    }, 5000);
                });
            });
            console.log(hoge_1.hoge);
        }
    };
});

```

</div></details>

## rootDir

```
"rootDir": "./src"
```

> Specify the root directory of input files. Use to control the output directory structure with --outDir.

コンパイル結果を`outDir`で出力する際に、どのディレクトリ配下のディレクトリ構造で出力するかを指定する。
`files`や`include`とは違い、コンパイル対象を決めるオプションではない。
逆に、それらのオプションで決まっているコンパイル対象となるファイルは、全て`rootDir`で指定するディレクトリ配下に存在する必要がある。

<details><summary>詳しく</summary><div>

例えば下記のディレクトリ構造で、`rootDir`を`./src`にしたとする。

```
.
├── index.ts
├── package-lock.json
├── package.json
├── src
│   ├── hoge.ts
│   └── piyo
│       ├── foo
│       │   └── foo.ts
│       └── piyo.ts
└── tsconfig.json
```

```tsconfig.json
"outDir": "./dist",
"rootDir": "./src"
```

`files`や`include`を指定していないので、コンパイル対象は`tsconfig.json`の存在するディレクトリ配下の全ての`.ts`、`.tsx`ファイル。この状態でコンパイルを実行すると、コンパイル対象が`rootDir`で指定したディレクトリ外に存在するため、以下のようにエラーが出る。

```console
error TS6059: File '/path/to/index.ts' is not under 'rootDir' '/path/to/src'. 'rootDir' is expected to contain all source files.
```

これは、実際のルートディレクトリに存在する`index.ts`が、コンパイル対象にも関わらず、`rootDir`で指定しているディレクトリ`./src`配下に存在しないため。

`include`でコンパイル対象を`./src/**/*`にすれば、`rootDir`に全てのコンパイル対象が含まれるためコンパイルが通る。

```tsconfig.json
"include": [
  "src/**/*"
]
```

コンパイル結果は下記（`./dist`のみ記載）。

```
dist/
├── hoge.js
└── piyo
    ├── foo
    │   └── foo.js
    └── piyo.js
```

この出力結果は、`rootDir`で指定している`./src`配下と同じディレクトリ構成。

</div></details>

## incremental

```
"incremental": true
```

> Enable incremental compilation

公式：https://devblogs.microsoft.com/typescript/announcing-typescript-3-4/

このオプションを`true`にすると、以前コンパイルを実行したコードと現在のコードとの差分を検出して、必要なファイルだけをコンパイルするようになる。
以前コンパイルを実行したコードの状態を保存するために、tscは出力先ディレクトリの`.tsbuildinfo`ファイルを利用する。
tscはこのファイルを自動で生成し、コンパイルした際には自動で更新するため、エンジニアが手動で変更を加えることはない。

`true`の場合、初回コンパイルの時間は長くなる（コンパイル状況を保存する処理が入るため）が、その後のコンパイルは差分のみを対象とするため早くなる。

ただし、開発の途中で`tsconfig.json`の設定を変えた場合などは、差分だけコンパイルしていると以前コンパイルしたコードが最新の`tsconfig.json`の設定に準拠しないコードになる可能性があるので注意。
`tsconfig.json`を変えたら、一度`.tsBuildInfo`を削除して1からコンパイルし直した方が良い。

## tsBuildInfoFile

```
"tsBuildInfoFile": "./dist/.diff"
```

> Specify file to store incremental compilation information

`incremental`オプションを`true`にした際に、`.tsbuildinfo`ファイルの場所を自分で指定したい場合にそのパスを指定する。
ファイル名を変更することも可能。

## removeComments

```json
"removeComments": true
```

> Do not emit comments to output.

コンパイル結果の出力ファイルから、コンパイル対象のファイル上のコメントを削除する。
ただし、著作権表示を表す`/*!`から始まるファイル先頭のコメントは、その直下に空行が存在する限り保持される。

```
/*!
 * Copyright 2019 Hoge
 */

export const Hoge = "HOGE";
```

参考： https://github.com/Microsoft/TypeScript/issues/12307

## noEmit

```json
"noEmit": true
```

> Do not emit outputs.

`true`にするとコンパイル結果を出力しなくなる。
tscによる型チェックだけを機能として利用したい場合（Babelなど他ツールが実際のコンパイルを行う場合）に使用する。

## importHelpers

```json
"importHelpers": true
```

> Import emit helpers from 'tslib'.

コンパイル結果にPolyfillが必要な場合、出力結果のjs上でそれら定義するのではなく、`tslib`から`import`することで出力結果のファイルサイズを削減する。

```console
$ npm install --save tslib
```

が必要。

<details><summary>詳しく</summary><div>

例えば、下記のコードを、`target`オプションなし（値はデフォルト値の`ES3`になる）でコンパイルしてみます。

```index.ts
export const func = async () => {
  return new Promise<string>(resolve => {
    setTimeout(() => {
      resolve("5秒経ちました");
    }, 5000);
  });
};
```

すると、結果は下記のように、ES3に準拠した形でコードを再現するためのPolyfillが上半分以上で定義されているのが分かります。

```index.js
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __generator = (this && this.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (_) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};
// ここまでPolyfillの定義
exports.__esModule = true;
exports.func = function () { return __awaiter(void 0, void 0, void 0, function () {
    return __generator(this, function (_a) {
        return [2, new Promise(function (resolve) {
                setTimeout(function () {
                    resolve("5秒経ちました");
                }, 5000);
            })];
    });
}); };
```

これは、１ファイルだけならまだ良いですが、複数のファイルで同じようにPolyfillが必要な記法を使用すると、全てのファイルにこの定義のコードが生成されてしまいます。
こういったPolyfillが必要な環境というのはだいたいの場合古いバージョンのブラウザなど、良いとは言えない環境であり、そういった環境においてjsコードのファイルサイズというのは重要なポイントになります。

そこで、このオプションを`true`にしてコンパイルした結果がこちらです:arrow_down:。

```index.js
"use strict";
exports.__esModule = true;
var tslib_1 = require("tslib");
exports.func = function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
    return tslib_1.__generator(this, function (_a) {
        return [2, new Promise(function (resolve) {
                setTimeout(function () {
                    resolve("5秒経ちました");
                }, 5000);
            })];
    });
}); };
```

Polyfillの定義が消え、

```index.js
var tslib_1 = require("tslib");
```

が追加されています。
つまり、ファイルごとに定義するのではなく、モジュールとして切り出してそれを参照するという形になりました。

もちろん、requireするということはそのモジュールが必要なので、これを有効にする場合は`tslib`をインストールします。

```console
$ npm install --save tslib
```

</div></details>

## downlevelIteration

```json
"downlevelIteration": true
```

> Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'.

`target`が`ES3`または`ES5`の時に、ジェネレータの`yield*`や`for..of`構文などのイテレータを使用した記法を配列・文字列以外で使用する際に`true`にする。
TypeScript 2.3で導入。


<details><summary>詳しく</summary><div>

ES6で導入されたイテレータですが、配列・文字列以外のiterableなオブジェクトに対してイテレータに準拠した記法を実行しようとすると、`target`が`ES3`・`ES5`の場合にエラーになります。

```ts
// これは配列なのでOK
const arr = [1, 2, 3];
for (const value of arr) {
  console.log(value);
}

// Setはiterableだけど配列ではないのでエラー
const map = new Set([1, 2, 3]);
for (const value of map) {
  console.log(value);
}
```

```
error TS2569: Type 'Set<number>' is not an array type or a string type. Use compiler option '--downlevelIteration' to allow iterating of iterators.
```

ジェネレータの`yield*`を配列・文字列以外で使用すると同様のエラーが出ます。


```ts
// これは配列なのでOK
function* func() {
  while (true) {
    const arr = [1, 2, 3];
    yield* arr;
  }
}

// Mapはiterablだけど配列・文字列ではないのでエラー
function* func() {
  while (true) {
    const map = new Map<string, string>();
    map.set("hoge", "HOGE");
    yield* map;
  }
}
```

```
error TS2569: Type 'Map<string, string>' is not an array type or a string type. Use compiler option '--downlevelIteration' to allow iterating of iterators.
```

ちなみに、これは自作のiterableなオブジェクトでも同様です。

```ts
class MyIterator {
  count = 0;
  max: number;

  constructor(max: number) {
    this.max = max;
  }

  next() {
    const done = this.count > this.max;
    const value = done ? undefined : this.count;

    this.count = this.count + 1;

    return { value, done };
  }
}

const iterator = new MyIterator(10);

const iterable = {
  [Symbol.iterator]() {
    return iterator;
  }
};

for (const value of iterable) {
  console.log(value);
}

function* func() {
  while (true) {
    yield* iterable;
  }
}
```

イテレータもiterableなオブジェクトも自分で書いたとして、このコードのコンパイル結果は

```
error TS2569: Type '{ [Symbol.iterator](): MyIterator; }' is not an array type or a string type. Use compiler option '--downlevelIteration' to allow iterating of iterators.
```

です。

これらは、`"downlevelIteration": true`にすることでコンパイルが通るようになります。

</div></details>

## isolatedModules

```json
"isolatedModules": true
```

> Transpile each file as a separate module (similar to 'ts.transpileModule').

コンパイル対象のファイル間の関係性を一切無視して、全てのファイルを単一のモジュールとしてコンパイルする。
その場合の安全でない記法についてコンパイル時にエラーを出すようにする。

これを`true`にした場合、コンパイル対象の全てのファイルが`export`構文を含む必要があり、コード中の

- `declare const enum`
- 型のre-export

はエラーとなりコンパイル出来ない。

<details><summary>詳しく</summary><div>

このオプションの提案のissue: https://github.com/microsoft/TypeScript/issues/2499
このオプションが追加されたPR: https://github.com/microsoft/TypeScript/pull/2550/

`isolatedModules`を`true`にすると、何も`export`していないファイルは、コード先頭で以下のようなエラーが出る。

```ts
const hoge = "hoge";
```

```
error TS1208: All files must be modules when the '--isolatedModules' flag is provided.
```

また、`declare const enum`と型のre-exportもエラーになる。

```hoge.ts
export type Hoge = string;
```

```index.ts
declare const enum FooBar {
  Foo = "foo",
  Bar = "bar"
}

export const str = `hoge: ${FooBar.Foo}`;

export { Hoge } from "./hoge";
```

```
error TS2748: Cannot access ambient const enums when the '--isolatedModules' flag is provided.

error TS1205: Cannot re-export a type when the '--isolatedModules' flag is provided.
```

re-exportに関しては、下記2点の回避策（[参考:create-react-app#6054](https://github.com/facebook/create-react-app/issues/6054)）がある。

1: re-export時の`export`を`export *`に変える。

```index.ts
// export { Hoge } from "./src";

export * from "./src";
```

2: re-export時に再定義する。

```index.ts
// export { Hoge } from "./src";

import { Hoge } from "./src";
export type ReExportedHoge = Hoge;
```

</div></details>

<details><summary>Next.js 9と`isolatedModules`</summary><div>

Next.jsでは、9からデフォルトでTypeScriptをサポートするようになった。
しかし、その方法はtscではなくBabel（[babel/preset-typescript](https://babeljs.io/docs/en/babel-preset-typescript)）を用いたトランスパイルであり、それに伴い`"isolatedModules": true`が必須になった。
今まで独自にtscでTypeScriptをコンパイルしてNextを使っている（かつ`"isolatedModules": false`である）場合、使用している`declare const enum`や型のre-exportが全てエラーになり、コンパイルが通らなくなる。
とにかくこれはもう書き直すしかない...

</div></details>

## strict

```
"strict": true
```

> Enable all strict type-checking options.

このオプション自体は特定の機能を有効にするものではなく、このオプションを`true`にすると、下記のオプションが全て`true`になる。

- `--noImplicitAny`
- `--noImplicitThis`
- `--alwaysStrict`
- `--strictBindCallApply`
- `--strictNullChecks`
- `--strictFunctionTypes`
- `--strictPropertyInitialization`

逆に言えば、`strict`を`true`にした上で、任意のルールを一つずつ`false`にすることが可能。

## noImplicitAny

```json
"noImplicitAny": true
```

> Raise error on expressions and declarations with an implied 'any' type.

暗黙的に`any`になる値をエラーにする。

<details><summary>詳しく</summary><div>

```obj.ts
const obj = {};
const hoge = obj["hoge"];

const arr = [];
const item = arr[0];
```

このコードの定数`hoge`は型が`any`になる。
また、`arr`は`any[]`になる。

これらはこのオプションを`true`にすると以下のようなエラーでコンパイルが失敗する。

```console
index.ts:14:14 - error TS7053: Element implicitly has an 'any' type because expression of type '"hoge"' can't be used to index type '{}'.
  Property 'hoge' does not exist on type '{}'.

14 const hoge = obj["hoge"];
                ~~~~~~~~~~~

index.ts:16:7 - error TS7034: Variable 'arr1' implicitly has type 'any[]' in some locations where its type cannot be determined.

16 const arr1 = [];
         ~~~~

index.ts:17:14 - error TS7005: Variable 'arr1' implicitly has an 'any[]' type.

17 const item = arr1[0];
```

回避するためには、以下のように明示的に型を書く。

```hoge.ts
const obj: Record<string, number> = {};
const hoge = obj["hoge"];

const arr1: string[] = [];
const item = arr1[0];
```

あとは、下記のように関数の引数なども。

[noImplicitAny - TypeScript Deep Dive 日本語版](https://typescript-jp.gitbook.io/deep-dive/intro/noimplicitany)

`any`になって良いことは何一つ無いので、必ず`true`で良いと思う。

</div></details>

## strictNullChecks

```json
"strictNullChecks": true
```

> Enable strict null checks.

Nullableな値に対してオプションの呼び出しを行う記述をエラーにする。

<details><summary>詳しく</summary><div>

```ts
type Obj = {
  hoge?: string;
};

const obj: Obj = {};
const trimmed = obj.hoge.trim();
```

`trim`は[String.prototype.trim](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/trim)。

このObj型のオプション`hoge`は`?`付きなので`undefined`が入りうる。
`hoge`が`undefined`の場合、`trim`を呼ぶとランタイムエラーになる。

このオプションが`true`の場合は、以下のようにコンパイル時にエラーになる。

```console
index.ts:25:17 - error TS2532: Object is possibly 'undefined'.

25 const trimmed = obj.hoge.trim();
```

これを回避するためには、値が`undefined`ではないことを保証する。例えば、

```ts
const obj: Obj = {};
if (obj.hoge != undefined) {
  const trimmed = obj.hoge.trim();
}
```

など。

ちなみに、`!`（`Non-Null Assertion Operator`）でもエラーを消すことができるが、実質ランタイムエラーになるだけなので、基本的にやってはいけない。
唯一許容できるとすれば、コードの論理上、非`undefined`であることが定まっているが、tscの型推論が効かない場合のみ。
例えば下記のようなコード。

```ts
const component = props.func && (
  <div onClick={() => props.func!()}>
    contents
  </div>
);
```

この場合、`props.func &&`を通っている時点で`props.func`が非`undefined`であることは確定しているが、jsxの中で渡そうとすると型推論が効かず、`!`をつけないとtscでエラーになる。
とは言え、`!`を使わなくて良いようなコードにすることを心がけたい。

</div></details>

## strictFunctionTypes

```
"strictFunctionTypes": true
```

> Enable strict checking of function types.

公式：https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html

関数代入時の引数の型チェックにおいて、TypeScriptのデフォルトはBivariantlyな挙動だが、このオプションを`true`にするとContravariantlyに型チェックが走るようになる。

Varianceについては下記の記事が参考になります。

- [ジェネリックの共変性と反変性 - Microsoft .NET](https://docs.microsoft.com/ja-jp/dotnet/standard/generics/covariance-and-contravariance)
- [Type Compatibility - TypeScript Deep Dive 日本語版](https://typescript-jp.gitbook.io/deep-dive/type-system/type-compatibility)
- [TypeScript 2.6 変更点と注意点 - abcdefGets](http://abcdef.gets.b6n.ch/entry/2017/11/01/101358)

<details><summary>詳しく</summary><div>

**Varianceとは、端的に言えば「型の違う変数同士を代入する際のルール」のことです。**
（ちなみにこの概念自体はTypeScript固有のものではなく、プログラミング言語において一般的に使用される概念です。）

ここで言う「型の違う」というのは、基本的には継承関係にある親子のクラス型間の話です。
つまり、`string`と`number`は継承関係に無いので、それらの型を持った変数同士が互いに代入不可能なのは当然です。

しかし、継承関係にある変数というのは、型が違っても代入可能な場合があります。
オブジェクト指向でポリモーフィズムと呼んでいる仕組みがまさにそれで、親クラス型の変数には、子クラス型の変数を代入することでき、これによって柔軟なコードを書くことができるようになります（下記のコードは仮想の言語で、雰囲気）。

```
class SmartPhone {
  call() { /* 電話をかける処理（このクラスを継承する子クラス全てに共通の、処理またはインターフェース） */ }
}
class iOSSmartPhone extends SmartPhone {
  purchaseByAppStore() { /* AppStoreで課金する処理（子クラスにしか存在しない処理） */ }
}
class AndroidSmartPhone extends SmartPhone {
  purchaseByPlayStore() { /* PlayStoreで課金する処理（子クラスにしか存在しない処理） */ }
}

iOSSmartPhone iosSp = new iOSSmartPhone();
AndroidSmartPhone androidSp = new AndroidSmartPhone();

SmartPhone[] sps = [ iosSp, androidSp ];

// OSが異なるスマホでも、callメソッドは共通しているため全部一括でcallメソッドを実行できる。
for (int i = 0; i < sps.length; i++) {
  sps[i].call();
}
```

この、「親クラス型の変数には子クラス型の変数を代入できるルール」のことを、Varianceでは**Covariant**（もしくはCovariance）と呼びます。
VarianceにはCovariantを含めた4つの種類が存在します。

1. Covariant/Covariance: 親クラス型の変数には、子クラス型の変数を代入できる。
2. Contravariant/Contravariance: 子クラス型の変数には、親クラス型の変数を代入できる。
3. Bivariant/Bivariance: 継承関係にあるクラス同士であれば、親でも子でも互いに代入できる。
4. Invariant/Invariance: 継承関係にあっても、型が異なれば代入はできない。

話を戻すと、TypeScriptでは関数代入時に引数の型チェックの挙動はデフォルトで**Bivariant**です。

ちなみに、関数同士の代入において、下記の条件は必須になります。

1. 関数の返り値は、代入先の関数の型の返り値型を全て満たしている。
    - 余分にある分には構わない。
2. 引数の数は、代入先の関数の引数の数以上である。
    - 多い分には構わない。
    - オプション引数（`?`つき）でも、個数を満たしていれば代入可能。
    - 可変長引数の場合は相手の引数に数に関わらず代入可能。

感覚的にはCovariantじゃないんだ、と思うんですが、実際に書いてみると関数の引数に関してはCovariantが危険であることがわかります。

```ts
class SmartPhone {
  // このクラスを継承するクラス全てに共通のメソッド
  call() {
    console.log("Calling...");
  }
}

class iOSSmartPhone extends SmartPhone {
  // 子クラス特有のメソッド
  openAppStore() {
    console.log("Opened!");
  }
}

let openAppStore: (sp: iOSSmartPhone) => void = sp => sp.openAppStore();
let callBySmartPhone: (sp: SmartPhone) => void = sp => sp.call();
```

の時に、

```ts
// デフォルトではOK、`strictFunctionTypes: true`の時にはError
callBySmartPhone = openAppStore;
// RuntimeError: 型定義的には親クラスのインスタンスを渡すのが正解だが、
//               実際の中身の処理ではそのインスタンスに対して子クラス特有のメソッドを呼び出しているため
callBySmartPhone(new SmartPhone());
```

```ts
// OK
openAppStore = callBySmartPhone;
// OK: 型定義的には子クラスのインスタンスを渡すが、
//     中の実際の処理では親クラスのメソッドを呼び出している。特に問題なし。
openAppStore(new iOSSmartPhone());
```

となるからです。

`strictFunctionTypes`を`true`にすることで、この危険なCovariantな関数代入を静的型チェックの段階でエラーにすることが出来ます。

TypeScriptは自由を求めてデフォルトでこの手のルールではゆるい方の挙動を取るけど、実際にはランタイムエラーを起こしうるので静的にチェックしてほしいところ。
つまり、これもとりあえず`true`にしておきましょう。

そもそもの話、Immutableを意識して`const`だけ使っていれば通常気にする必要は無い話ではあると思うけど...

<details><summary>ちなみに（Contravariantも危険だっていう話）</summary><div>

実は、Contravariantもランタイムエラーを引き起こす可能性があります。

https://typescript-jp.gitbook.io/deep-dive/type-system/type-compatibility

ここを読んでいて面白かったので紹介します。

```ts
animalArr = catArr; // Okay if covariant
animalArr.push(new Animal('another animal')); // Just pushed an animal into catArr!
catArr.forEach(c => c.meow()); // Allowed but BANG 🔫 at runtime
```

この部分。
`Cat`は`Animal`クラスの子クラスで、`animalArr`、`catArr`はそれぞれ`Animal`の配列と`Cat`の配列。

1行目で、親クラスの配列型に対して、子クラスの配列型を代入しています。
これはCovariantなので大丈夫なように感じるんですが、配列の場合 代入後は双方の変数が同じ値を参照するので、`animalArr = catArr;`の後に`animalArr.push()`をすると、`catArr`にも要素が追加されます。

ので、その配列に親クラス（`Animal`）型の要素を`push`した後に、うっかり`catArr`に対して`forEach`で子クラス（`Cat`）特有のメソッドを呼び出すと、型定義は間違っていないのに、配列の中に親クラスのインスタンスが入っているため、ランタイムエラーになります。

ひえ〜

> JavaScriptのようなミュータブル(変更可能)なデータの存在下で、完全に健全な型システムのためにはinvariantが唯一有効なオプションです。

ということですね。

</div></details>

</div></details>

## strictBindCallApply

```json
"strictBindCallApply": true
```

> Enable strict 'bind', 'call', and 'apply' methods on functions.

`bind`, `call`, `apply`を使用する際に、より厳密に型チェックが行われるようになる。

公式ドキュメント： https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html

TODO: 詳しく

## strictPropertyInitialization

```json
"strictPropertyInitialization": true
```

> Enable strict checking of property initialization in classes.

クラス定義時、インスタンス変数の初期化が宣言時、もしくはコンストラクタのどちらでも行われていない場合にエラーになる。
TypeScript2.7で導入。

https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html

<details><summary>詳しく</summary><div>

```index.ts
class C {
  foo: number;
  bar = "hello";
  baz: boolean;
  //  ~~~
  //  Error! Property 'baz' has no initializer and is not assigned directly in the constructor.
  constructor() {
    this.foo = 42;
  }
}
```

```
error TS2564: Property 'baz' has no initializer and is not definitely assigned in the constructor.
```

この`baz`は宣言時もコンストラクタでも初期化されていない。

エラーを回避するためには、

```index.ts
  baz: boolean = false;
```

このように宣言時に初期化するか、もしくは

```index.ts
  constructor() {
    this.foo = 42;
    this.baz = false;
  }
```

コンストラクタで初期化する。

また、`!`（definite assignment assertion modifier）を変数宣言時につけることで、強制的にエラーを消すことができる。

これは、DIなどで外部から代入されることを想定している場合などに役立つ。
Non-null Assertion Operatorをあまり使わないようにするのと同様に、基本的には初期化するという正当な方法でエラーを回避するべき。

</div></details>

## noImplicitThis

```json
"noImplicitThis": true
```

> Raise error on 'this' expressions with an implied 'any' type.

使われている`this`の型が暗黙的に`any`になる場合にエラーにする。

<details><summary>詳しく</summary><div>

```index.ts
const func = function() {
  console.log(this);
};
```

このコードは、下記のエラーが出ます。

```
error TS2683: 'this' implicitly has type 'any' because it does not have a type annotation.
```

`function`による関数の場合、thisの値は宣言時に定まらないため、暗黙的に型はanyになるから。

これを回避するためには2種類の方法がある。

1: アロー関数を使う

アロー関数の場合、`this`はそのアロー関数の定義コンテキストの`this`を参照するため、定義コンテキストで`this`が定まる場合で、かつそれが意図している参照なのであればアロー関数にするだけで良い。

例えば、

```index.ts
const obj = {
  count: 0,
  hoge: function(label: string) {
    return function() {
      console.log(`${label}: ${this.count}`);
    };
  }
};
```

（実用性は何も考えないとして）上記のように`function`による関数を`return`している場合、意図としては`obj.count`を参照したいが、`function`では`bind`を使わないと`this`が定まらない。
（ちなみに、仮にこの返り値の関数を`bind(this)`してから`return`してもエラーは消えない）

こういう場合はアロー関数にするだけで良い。

```index.ts
const obj = {
  count: 0,
  hoge: function(label: string) {
    return () => {
      console.log(`${label}: ${this.count}`);
    };
  }
};
```

2: 明示的に`this`の型を指定する。

TypeScriptでは、`function`による関数宣言で作られる関数の第一引数の名前が`this`の場合、その引数の型は関数内の`this`の型を指す（アロー関数にはこの機能は存在しない: `'An arrow function cannot have a 'this' parameter.ts(2730)'`）。
そしてその場合、2個目以降の引数が実際のその関数の引数になる。

例えば下記のような、`this`を`console.log`する関数があったとして、

```index.ts
const logThis = function() {
  console.log(this);
};
```

これは

```
error TS2683: 'this' implicitly has type 'any' because it does not have a type annotation.
```

が出るのでコンパイル出来ない。
しかし、この関数はアロー関数に変えても別のエラーが出る。

```
error TS7041: The containing arrow function captures the global value of 'this'.
```

そこで、

```index.ts
const logThis = function(this: object) {
  console.log(this);
};
```

このように引数でthisを指定すると、`console.log(this);`部分の`this`は型が定まる（この場合は`object`）。

この書き方をした場合は、2個目以降の引数が実際の関数の引数になるため、呼び出しは引数を何も取らない形で実行できる。

```index.ts
const logThis = function(this: object) {
  console.log(`this`);
};

const obj = { logThis };

obj.logThis();
```

引数が欲しい場合はこう。

```index.ts
const logThis = function(this: object, label: string) {
  console.log(`${label}: ${this}`);
};

const obj = { logThis };

obj.logThis("HOGEHOGE:");
```

出力されるjsを見れば通常の関数として扱われているのがわかる。

```index.js
var logThis = function (label) {
    console.log(label + ": " + this);
};
var obj = { logThis: logThis };
obj.logThis("HOGEHOGE");
```

</div></details>

## alwaysStrict

```json
"alwaysStrict": true
```

> Parse in strict mode and emit "use strict" for each source file.

`"use strict";`を必ず全てのファイルの先頭行に付与する。

参考： https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Strict_mode

## moduleResolution

```json
"moduleResolution": "node"
```

> Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6).

公式ドキュメント： https://www.typescriptlang.org/docs/handbook/module-resolution.html

tscのモジュール解決の方法を指定する。
値は`"node"`か`"classic"`。
デフォルト値は、`module`の指定値が`AMD`・`System`・`ES2015`のいずれかである場合は`classic`、それ以外の場合は`node`。

classicが元々tsでデフォルトで使われていた方法ですが、主に後方互換のために残してあると明記してあるので、新しい環境でやる場合はnodeにしておきましょう。

<details><summary>詳しく</summary><div>

モジュール解決（Module Resolution）とは、tscが`import`文を解釈する際に、その`import`が参照する定義ファイルを特定するプロセスのこと。

まず、モジュール解決にはrelativeとnon-relativeの2種類が存在する。

### `relative`

import文のfromで指定する文字列が`/`、`./`、`../`のいずれかで始まる、つまりパスを指定している場合。
基本的にimportしたいファイルが直接そのレポジトリに入っている場合に使用する。

### `non-relative`

それ以外、つまり通常npm installしたパッケージをimportする時のようにいきなり単語を指定している場合。
`baseUrl`で指定した先、もしくは`paths`で指定したパスマッピングの先、そしてmoduleのアンビエント宣言はnon-relativeにだけ適用される。

その上で、tsでは名前解決の方法にnodeもしくはclassicという２種類が存在する。

### `classic`（古い）

これは非常にそのままで、relativeの場合はその指定したパスにあるファイルを、non-relativeの場合は、`指定した文字列.ts`なファイルを現在の階層も含めてレポジトリのルートディレクトリまで1個ずつ遡って探す、という方法。

node_modulesとか一切関係なく、ひたすらファイル名だけが考慮される。現代では使用することほとんど無いと思うので説明あっさり。

### `node`（現状のおすすめ）

`node`はNode.jsのモジュール解決を模倣している方法。

まずNodeがどうやって名前解決するかの説明。

#### Nodeにおける、relativeの場合

基本的には指定したファイルを読みにいく。
が、classicと違うのは、**指定したパスがディレクトリの場合に、そのディレクトリのpackage.jsonでmainに指定したファイル、もしくはそのディレクトリ直下のindex.jsを読む**、という点。
優先順位的には、 `/src/path/to/a.ts`が`import ... from "./b"`していた場合、

1. `/src/path/to/b.js`
2. `/src/path/to/main.js`（`/src/path/to/package.json`が存在し、その中で`"main": "main.js"`という記述があった場合のみ）
3. `/src/path/to/index.js`

#### Nodeにおける、non-relativeの場合

Nodeでは、non-relativeなimportはすなわち`node_modules`からのimportを意味する。
基本的な読み込みルールは上で書いたrelativeと変わらず（指定した単語.js、もしくはpackage.jsonとかindex.jsとか）、`node_modules`というディレクトリの中のみ探索対象とする。
classicと同様、階層をどんどん上に遡って見ていく。

つまり、 `/src/path/to/a.ts`が`import ... from "b"`していた場合、

1. `/src/path/to/node_modules/b.js`
2. `/src/path/to/node_modules/b/hoge.js`（package.jsonがあって"main"で指定してたら）
3. `/src/path/to/node_modules/b/index.js`
4. `/src/path/node_modules/b.js`
5. `/src/path/node_modules/hoge.js`（package.jsonがあって"main"で指定してたら）
4. `/src/path/node_modules/b/index.js`
4. `/src/node_modules/b.js`
5. `/src/node_modules/hoge.js`（package.jsonがあって"main"で指定してたら）
4. `/src/node_modules/b/index.js`
5. `/node_modules/b.js`
5. `/node_modules/hoge.js`（package.jsonがあって"main"で指定してたら）
4. `/node_modules/b/index.js`

な感じ。

さて、やっとtsにおける読み込み順序の話。

#### tsにおける、relative

基本的にNodeと同じ。ただし、読み込むファイルの拡張子が`.js`だけでなく

1. `.ts`
2. `.tsx`
3. `.d.ts`

となる（上記は読み込む優先度順）。

さらに、package.jsonの`"types"`に指定したファイルを`"main"`に指定したファイルの型定義ファイルとして参照する。
（package.jsonの`"main"`にtsファイルが指定されることはない（あったとしたらインストール後にモジュール側のコンパイルも必要になってしまう）ので、ts的には`"main"`の値は関知しない）

パッケージで提供するモジュールの型定義は`@types/xxx`に置くこともできるが、公式にパッケージ自体がtsの型定義を持つのが利用者としては一番楽だ。
その方法が、package.jsonの`"types"`に型定義ファイルを指定する、もしくはルートディレクトリに`index.d.ts`を置くこと。

#### tsにおける、non-relative

これも基本的にNodeと同じですが、relativeと同様に拡張子が３種類になる。
一点明確に違うのは、`node_modules/@types`配下の型定義ファイルも参照の対象になるという点。

優先順位的には

1. `/src/path/to/node_modules/b.ts`
1. `/src/path/to/node_modules/b.tsx`
1. `/src/path/to/node_modules/b.d.ts`
1. `/src/path/to/node_modules/b/hoge.d.ts`（package.jsonのtypesで指定されていたら）
1. `/src/path/to/node_modules/@types/b.d.ts`
1. `/src/path/to/node_modules/b/index.ts`
1. `/src/path/to/node_modules/b/index.tsx`
1. `/src/path/to/node_modules/b/index.d.ts`


</div></details>

## baseUrl

```json
"baseUrl": "./"
```

> Base directory to resolve non-absolute module names.

non-relativeなimportにおいて、相対的なカレントディレクトリをどこにするか指定する。
値が`./`の場合はtsconfig.jsonが置いてあるディレクトリを指す。

relativeなimportには一切関係しない。

## composite

```json
"composite": true
```

> Enable project compilation

[Project References](https://www.typescriptlang.org/docs/handbook/project-references.html)を有効にする際に、`references`で指定された`tsconfig.json`はこの値を`true`にする。

## noUnusedLocals

```json
"noUnusedLocals": true
```

> Report errors on unused locals.

宣言されたが使用されていない変数が存在する場合にコンパイルエラーにする。
デフォルト値は`false`。とりあえず`true`にしておけ系。

開発中にめんどくさいみたいな時は一時的に`false`にしたりするかも。

## noUnusedParameters

```json
"noUnusedParameters": true
```

> Report errors on unused parameters.

関数の作成時、定義しているのに中身のコードで使用されない場合にコンパイルエラーにする。
デフォルト`false`。とりあえず`true`にしておけ...系？少なくとも自分は`true`で良いと思う。

<details><summary>詳しく</summary><div>

使わない引数は書かなければ良いのだが、例えば第二引数は使うんだけど第一引数は使わない、みたいな場合はどうしても定義しないといけなくなる。
そういう場合は、使わない引数のprefixとして`_`アンダースコアを付与するとエラーを回避できる。
jsは仕組みで縛れないけど「使うなよ！絶対使うなよ！」っていう値にアンダースコアをつける文化ですね。
明示的に「これは使わない変数です」っていうのをわかりやすくすればOK、みたいなイメージ。

```ts
// これはhogeを関数内で使用していないのでコンパイルエラー
const func = (hoge: string, piyo: string) => {
  console.log("HOGE!!! and " + piyo);
};
// index.ts:1:15 - error TS6133: 'hoge' is declared but its value is never read.
```

```ts
// 使っていない第一引数にアンダースコアを追加したのでコンパイルが通る
const func = (_hoge: string, piyo: string) => {
  console.log("HOGE!!! and " + piyo);
};

// ちなみにアンダースコアだけでも通る
const func = (_: string, piyo: string) => {
  console.log("HOGE!!! and " + piyo);
};
```

</div></details>

## noImplicitReturns

```json
"noImplicitReturns": true
```

> Report error when not all code paths in function return a value.

all code pathsっていうのは、条件分岐した場合に全ての状況で、という意味ですね。
つまり関数内で、条件分岐の条件によって明示的な`return`がされないルートがある場合、コンパイルエラーになります。

このエラーが出る場合、だいたいは設計ミスでもっと良い書き方がある（早期リターンとか関数の分離とか）気もするので、それに気づかせてくれるという意味でとりあえず`true`にしておけば良い気はします。

<details><summary>詳しく</summary><div>

```ts
// hogeがfalseの場合に明示的な`return`が無いのでコンパイルエラー
const func = (hoge: boolean) => {
  if (hoge) {
    return "HOGE!!!";
  }
};
// index.ts:1:14 - error TS7030: Not all code paths return a value.
```

```ts
// hogeがfalseの場合に明示的にundefinedを返しているのでコンパイルが通る
const func = (hoge: boolean) => {
  if (hoge) {
    return "HOGE!!!";
  }

  return;
};
```

ちなみに、関数の返り値の型を明示的に指定している場合は、このオプションが`false`であっても型が異なればエラーが出ます。

```ts
// "noImplicitReturns": false

// string型を返すことになっているが、hogeがfalseだった場合にundefinedが返るのでコンパイルエラー。
const func = (hoge: boolean): string => {
  if (hoge) {
    return "HOGE!!!";
  }
};
// index.ts:1:31 - error TS2366: Function lacks ending return statement and return type does not include 'undefined'.
```

```ts
// "noImplicitReturns": false

// 返り値の型がundefinedとのユニオン型になったのでコンパイルが通る。
const func = (hoge: boolean): string | undefined => {
  if (hoge) {
    return "HOGE!!!";
  }
};

```

</div></details>

## noFallthroughCasesInSwitch

```json
"noFallthroughCasesInSwitch": true
```

> Report errors for fallthrough cases in switch statement.

fallthroughというのはswitch文のcase内でbreakが無い場合に、その下のcaseの処理も実行される仕様のことです。
jsではfallthroughが発生するので、breakを書かないとどんどん下のcase文が実行されていきます。

これオプション名からわかりにくいんですが、**fallthroughなcaseのうち、1行以上処理が存在しているにも関わらず脱出処理（breakやreturn）が無いものにエラーを吐きます。**

とりあえず`true`にしておけ系。

<details><summary>詳しく</summary><div>

上で太字にした部分を説明します。

Rubyを書いているとcase文（jsで言うswitch文のこと）の中でwhen句（jsで言うcaseのこと）に複数の値を指定できるのが結構便利だったりします。jsではcase文に複数の値を指定できないので、そういう時はswitch文のfallthroughを利用したくなります。

```ts
// "noFallthroughCasesInSwitch": true
const func = (hoge: string) => {
  switch (hoge) {
    case "HOGE":
    case "HOGE!!!":
    case "HOGE??":
    case "HOGE~~~~":
      return "This is HOGE!!!";
    case "piyo":
    case "PIYO":
    case "PIYO!!!":
      return "This is PIYO!!!";
  }
};
```

この書き方はjs的にはなんら問題なく動きますし、**`"noFallthroughCasesInSwitch": true`であってもtsのコンパイルも通ります。**
この例の場合、複数条件指定のつもりで書いているfallthroughなcaseには処理が1行もありません。
ので、上で太字にした「1行以上処理が存在しているのに脱出処理が無い」という条件に当てはまりません。

逆に、下記のコードはコンパイルエラーです。

```ts
// "noFallthroughCasesInSwitch": true
const func = (hoge: string) => {
  let result;

  switch (hoge) {
    case "HOGE":
    case "HOGE!!!":
      console.log("HOGE!!"); // 1行以上の処理があるのにbreakもreturnも無いのでエラー
    case "HOGE??":
    case "HOGE~~~~":
      return "This is HOGE!!!";
    case "piyo":
    case "PIYO":
      result = "PIYO"; // 1行以上の処理があるのにbreakもreturnも無いのでエラー
    case "PIYO!!!":
      return "This is PIYO!!!";
  }

  return result;
};
```

```
index.ts:7:5 - error TS7029: Fallthrough case in switch.

7     case "HOGE!!!":
      ~~~~~~~~~~~~~~~

index.ts:13:5 - error TS7029: Fallthrough case in switch.

13     case "PIYO":
       ~~~~~~~~~~~~


Found 2 errors.
```

fallthroughは嫌いな人も多いわけですが、「複数の条件を指定したい場合」に限って言えば許されるようです。
個人的にも、fallthroughを複数条件指定以外で使う蓋然性が高いコードというのは見たことが無いので、このオプションはtrueで良いと思います。

</div></details>

## noUncheckedIndexedAccess

```json
"noUncheckedIndexedAccess": true
```

> Include 'undefined' in index signature results.

`strictNullChecks`オプションが有効の場合でも、
配列の要素やプロパティへのアクセスは厳密に型チェックできませんが、
`undefined`の可能性がある場合にエラーを吐かせるようにできます。

参考： https://tech.techtouch.jp/entry/update-typescript-4.1

## forceConsistentCasingInFileNames

```json
"forceConsistentCasingInFileNames": true
```

> Disallow inconsistently-cased references to the same file.

import時にファイルパスの文字列で大文字小文字を区別するかどうかを指定する。
デフォルトfalse。
Windowsは大小区別しないらしい（Winわからん）。
元々区別するOSでtrueになってても弊害は無いので、とりあえずtrueにしておけばOK。



この先工事中...

Next:

- paths
- rootDirs
- typeRoots
- types
- allowSyntheticDefaultImports
- esModuleInterop
- preserveSymlinks
- allowUmdGlobalAccess
- sourceRoot
- mapRoot
- inlineSourceMap
- inlineSources
- experimentalDecorators
- emitDecoratorMetadata