【TypeScript】意外と曖昧になりがち、、、any型、unknown型、never型の違いについて整理

# はじめに
業務などでTypeScriptを触っていく中で、たびたび見るany型、unknown型、never型。
これらに対して毎回「あれ、違いなんだっけ？」となってしまうので、、[サバイバルTypeScript](https://typescriptbook.jp/)を基にこの記事で整理しようと思います！

# any型
まず`any`型を見ていきます。
サバイバルTypeScriptによると以下のようです。
> TypeScriptのany型は、どんな型でも代入を許す型です。プリミティブ型であれオブジェクトであれ何を代入してもエラーになりません。

参考：[サバイバルTypeScript-any型](https://typescriptbook.jp/reference/values-types-variables/any)

`any` 型は **TypeScriptの型チェックを無効化**します。  
なのでboolean型だろうが、number型だろうが、どんな型の値でも格納できてしまいます。
```TypeScript
let anyType: any = "stringです"
anyType = true // boolean型も代入できてしまう
anyType = 1111 // number型も代入できてしまう
```
また、`any`型の変数は どんな型の変数にも代入可能 です。
```typescript
const anyType: any = "any型です";
const num: number = anyType; // エラーなし
const bool: boolean = anyType; // エラーなし
```
このように`any`型を使うと型チェックが完全に無効化されるため、型の安全性が失われてしまいます。
あくまで最終手段として使うのが良さそうです。

# unknown型
続いて`unknown`型を見ていきます。
`unknown`型は以下のようです。
> TypeScriptのunknown型は、型が何かわからないときに使う型です。
unknown型にはどのような値も代入できます。

参考：[サバイバルTypeScript-unknown型](https://typescriptbook.jp/reference/statements/unknown)

どんな型でも格納できるという点では`any`型と同じです。
```TypeScript
let unknownType: unknown = "stringです"
unknownType = true // boolean型も代入できてしまう
unknownType = 1111 // number型も代入できてしまう
```
しかし、`unknown`型の値を他の型の変数に代入しようとするとエラーになるという制約があります。
その点で`any`型とは異なります。
```typescript
const unknownType: unknown = "unknown型です";
//↓エラー発生：Type 'unknown' is not assignable to type 'number'. 
const int: number = unknownType; 
//↓エラー発生：Type 'unknown' is not assignable to type 'boolean'.
const bool: boolean = unknownType; 
```
他の型に代入したい場合は以下のように型ガードをつかいます。
```typescript
const unknownType: unknown = "unknownです。"

if (typeof unknownType === "string") {
  // ここでは、string型として扱える
  // エラーは発生しない
  const str: string = unknownType
}
```
any型みたいに柔軟に型を使いたいが、型安全性は保ちたい、、、。そんな時にunknown型が使えそうです。

# never型
最後に`never`型を見ていきます。
`never`型は以下になります。
> never型は「値を持たない」を意味するTypeScriptの特別な型です。

参考：[サバイバルTypeScript-never型](https://typescriptbook.jp/reference/statements/never)
`any`型と`unknown`型ではどんな型でも格納できますが、`never`型に関しては**値を一切持てません**。
格納できるのは`never`型のみになります。
```typescript
//↓エラーが発生：Type '"neverです"' is not assignable to type 'never'.
const neverType: never = "never型です";
//これはOK
const neverType: never = "neverです" as never
```
ですが、どんな型に対しても代入はできるみたいです。
```typescript
const neverType: never = "neverです" as never
const stringType: string = neverType //エラーなし
const intType: number = neverType //エラーなし
```
`never`型は、主に以下のように値も返さない状態を表すために使われます。

例1: 例外を投げる場合
```typescript
function throwError(message: string): never {
  throw new Error(message);
}
```
[参考：サバイバルTypeScript-never型](https://typescriptbook.jp/reference/statements/never#%E5%80%A4%E3%81%8C%E7%84%A1%E3%81%84%E3%81%A8%E3%81%AF)
例2: 無限ループする場合
```typescript
function forever(): never {
  while (true) {} // 無限ループ
}
```
[参考：サバイバルTypeScript-never型](https://typescriptbook.jp/reference/statements/never#%E5%80%A4%E3%81%8C%E7%84%A1%E3%81%84%E3%81%A8%E3%81%AF)
# まとめ
`any`型`unknown`型`never`型の違いを整理すると、以下のようになります。
| 型        | 特徴                         | 代入時の挙動                          |
|-----------|----------------------------- |--------------------------------------|
| `any`      | どんな型でも格納可能         | どの型にも代入可能|
| `unknown`  | どんな型でも格納可能        | 型ガードすればどの型にも代入可能   |
| `never` 　 | 値を持たない| どんな型にも代入できるが、値は持てない|
### 使い道
`any`型は型チェックを無視するため、基本的には使用を避けるほうが好ましい。
`unknown`型は安全性を保ちつつ柔軟に使えるため、どの型を持つか不明な場合に有効。
`never`型は例外が発生する関数の戻り値などで使用。

記事に書いたことで違いが整理されたような気がします。
僕と同じように「結局、この3つの違いって何だっけ？」と悩む方のお役に立てれば嬉しいです。