TypeScriptでstrict trueにするとどうなるか

TypeScriptをインストールし、`tsc --init`をすると`tsconfig.json`を作成することができますが、その中に以下のような記述があります。

```typescript
    "strict": true, /* Enable all strict type-checking options. */
```

この`"strict": true`をつけることで型チェックを厳しくすることができますが、実際どんな設定が有効化されるのかを調べてみました。

## 結論

 現在 (typescript version 4.4.2) は以下の8つの項目が有効化されるようです。 (参考: [tsc CLI Options](https://www.typescriptlang.org/docs/handbook/compiler-options.html))

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

ただし[TSConfigリファレンス](https://www.typescriptlang.org/tsconfig#strict) にあるように、TypeScriptのバージョンアップとともに、新しい型チェックが追加される可能性もあるとのことです。

以下ではそれぞれの項目についてまとめていきます。

### [alwaysStrict](https://www.typescriptlang.org/tsconfig#alwaysStrict)

ES5で導入された[Strictモード](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Strict_mode)を適用します。
有効化されると以下のような変更が加えられます。

> 1. エラーではないが落とし穴になる一部の事柄を、エラーが発生するように変更することで除去します。
> 2. JavaScript エンジンによる最適化処理を困難にする誤りを修正します。Strict モードのコードは、非 Strict モードのコードより高速に実行できる可能性があります。
> 3. 将来の ECMAScript で定義される予定の構文の使用を禁止します。

具体的には、削除できないプロパティを消したり、代入不可のグローバル変数に代入するなどしたときに、通常であれば何も起きないところを例外が発生するようになったりといった変更が起きるようです。

### [noImplicitAny](https://www.typescriptlang.org/tsconfig#noImplicitAny)

型アノテーションが無く、他の型が推論できない場合、最終的に`any`型が推論されますが、この`any`が推論された場合にエラーとなります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143317/00796c4a-39c3-e73c-bb1a-d4c2bf3bde06.png)

### [noImplicitThis](https://www.typescriptlang.org/tsconfig#noImplicitThis)

thisの型が`any`のときにエラーになります。
以下の例のように、bindを使用することで、あらゆるものが`this`に渡される可能性がありました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143317/9b7b1176-79c5-7f05-573f-fb985ad18cbf.png)

### [strictBindCallApply](https://www.typescriptlang.org/tsconfig#strictBindCallApply)

bind, call, anyの第2引数以降は、以下の例の`person1`のように関数の引数の型とは異なるものが渡されても通常だとエラーになりません。
この設定を有効にすることで引数が適切かどうかをチェックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143317/196438ef-bc78-521f-f59d-942a12e75014.png)

### [strictFunctionTypes](https://www.typescriptlang.org/tsconfig#strictFunctionTypes)

関数の引数の型を厳格にチェックします。
以下の例だと、stringFuncの引数は`string`ですが、定義しようとした関数は`string | number`を引数にしようとしてエラーになっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143317/d5f537ce-a05b-5c97-5a9c-9d11247bed15.png)

### [strictNullChecks](https://www.typescriptlang.org/tsconfig#strictNullChecks)

この設定が無効化されている場合、`undefined`と`null`は無視してメソッド、プロパティ等の呼び出しが可能です。
以下の例だと、`name`が`undefined`の可能性もあるので、`length`を呼び出すことはできないですが、設定が無効化されている場合はエラーが表示されません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143317/b9fae6b8-6f17-7b85-f90d-baace8f7f94c.png)

### [strictPropertyInitialization](https://www.typescriptlang.org/tsconfig#strictPropertyInitialization)

宣言されているけどconstructorでsetされていないClassプロパティに対してエラーを表示します。
以下の例だと、`name`は constructorで設定されており、`accountType`はデフォルト値がセットされており、`address`はundefinedが許容されていますが、`email`はセットされていないためエラーとなります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143317/f5a80373-27aa-5f52-db44-92f331f22030.png)

### [useUnknownInCatchVariables](https://www.typescriptlang.org/tsconfig#useUnknownInCatchVariables)

このフラグはTypeScript4.4から導入された比較的新しいフラグです。JavaScriptでは様々な値を`throw`し、`catch`することが可能です。そのため、もともとは`catch`した変数は`any`型でした。
しかしこのフラグを有効化することで、型が`unknown`に変わります。
この変数を使用するためには以下の例のように型を特定する必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143317/8ec16641-27fe-6043-4fe3-c157478dc668.png)

## その他

今回説明したものは、strict trueにすると有効になるフラグだけですが、TypeScriptにはその他にも、以下のような型に関するフラグもありますので興味がある方は調べてみてください。

- [noUnusedLocals](https://www.typescriptlang.org/tsconfig#noUnusedLocals)
- [noUnusedParameters](https://www.typescriptlang.org/tsconfig#noUnusedParameters)
- [exactOptionalPropertyTypes](https://www.typescriptlang.org/tsconfig#exactOptionalPropertyTypes)
- [noImplicitReturns](https://www.typescriptlang.org/tsconfig#noImplicitReturns)
- [noFallthroughCasesInSwitch](https://www.typescriptlang.org/tsconfig#noFallthroughCasesInSwitch)
- [noUncheckedIndexedAccess](https://www.typescriptlang.org/tsconfig#noUncheckedIndexedAccess)
- [noImplicitOverride](https://www.typescriptlang.org/tsconfig#noImplicitOverride)
- [noPropertyAccessFromIndexSignature](https://www.typescriptlang.org/tsconfig#noPropertyAccessFromIndexSignature)