TypeScriptをなんとなく理解するための記事② ~型を組み合わせる: Union~

# この記事は何？

TypeScriptとは何か、何がいいのかを伝えようと頑張った記事の**第２弾**です！

今回は、型を組み合わせて新たな型を生成する、
**Union**について説明していきます。

@ 過去の記事、続編👇も合わせて御覧ください！
　1. [JavaScriptを知っている方がTypeScriptをなんとなく理解するための記事① ~はじめに~](https://qiita.com/NOMURA_keibyou38/items/06a3218de3ff480ce9de)
　2. TypeScriptをなんとなく理解するための記事② ~型を組み合わせる: Union~ `← この記事`
　3. [TypeScriptをなんとなく理解するための記事③ ~汎用的な型を作成する: Generics~](https://qiita.com/NOMURA_keibyou38/items/45974b8f802c51fe5a1d)
　4. [TypeScriptをなんとなく理解するための記事④ ~構造型~](https://qiita.com/NOMURA_keibyou38/items/5f1126cd39469f6f9faa)
@ TypeScriptがなんとなく理解できたら、是非インストールして、触ってみてください！
　👉 [【画像で説明】シンプルにTypeScriptを導入して使う方法](https://qiita.com/NOMURA_keibyou38/items/2cbb5971cea1ef6e83f5)

# 型の組み合わせとは？

TypeScriptでは、型と型を組み合わせて新しく型を作り上げることが出来ます。
この型の組み合わせの方法は２つあります。
１つは、**Union**、もう１つは、**Generics**です。

この記事では、**Union**の概要について説明していきます。

※Genericsについては[次回の記事](https://qiita.com/NOMURA_keibyou38/items/45974b8f802c51fe5a1d)で説明しています。

# Unionによる型の作成

### unionの基本
まずは、Unioinを使わずに型を作ってみます。
型は`type`を利用して、以下のように作成します。

```typescript
type Fish = "sanma";
```
新しく`Fish`型を作成しました。
この`Fish`型は、文字列(string)の`sanma`のみを許容する型です。
そのため、この型を使って以下のように、定数`lunch`を定義できます。

```typescript
type Fish = "sanma";
const lunch: Fish = "sanma";
```

`lunch`は`Fish`型なので、`"sanma"`のみ許容します。
つまり、ランチにはサンマしか食べることが出来ません。
実際に`lunch`にサンマ以外を定義しようとすると...

```typescript
const lunch: Fish = "iwana"; // タイプ '"iwana"'はタイプ '"sanma"'に割り当てることができません。ts（2322）
```

`Fish`型の`lunch`には、`"iwana"`を定義することが出来ませんでした。
ランチには、サンマもイワナも食べるので、どちらも許容したいです。
そこで、`Union`を利用します。`Union`は`|`を利用して次のように記述します。

```typescript
type Fish = "sanma" | "iwana";
const lunch: Fish = "iwana";
```

このように`|`を利用して`Fish`型に`"sanma"`, `"iwana"`に絞る事ができます。

ちなみに、`"sanma"`, `"iwana"`以外は許容されません。

```typescript
type Fish = "sanma" | "iwana";
const lunch: Fish = "iwana";
const dinner: Fish = "sanma";
const breakfirst: Fish = "saba"; // タイプ '"saba"'はタイプ 'Fish'に割り当てることができません。
```

もちろん数値も扱うことができます。

```typescript
type AndroidVersion = 9 | 10 | 11;
const myAndroidOsVersion: AndroidVersion = 11;
```

### ちょっと発展した型の作成

以上では、明確な文字や数値に限定して、型を作成しました。
ここまで厳格にしなくても、「文字列`string`はOK!」「文字列の入った配列`string[]`はOK!」ということも出来ます。

具体的には、以下のような記述方法です。

```typescript
type Food = string | string[];

const branch: Food = 'cake';
const nightMeal: Food = ['ramen', 'onigiri', 'potechi'];
const theLastSupper: Food = ['ramen', 'onigiri', 1498]; // タイプ「number」はタイプ「string」に割り当てることができません。ts（2322）
```

レオナルド・ダ・ヴィンチ作の最後の晩餐（`theLastSupper`）は、1498年に完成しましたが、これは数値であり、文字列でないのでエラーが起きます。

ちなみに、このような`Union`で型を定義した際に便利なのが型のチェックです。

以下のように、型のチェックをすることができます。

| タイプ | 述語 |
|:-:|:-:|
| 文字列  |  `typeof s === "string"` |
| 数値  | `typeof n === "number"`  |
| ブール値  | `typeof b === "boolean"`  |
| 未定義  | `typeof undefined === "undefined"`  |
| 関数  | `typeof f === "function"`  |
| 配列  | `Array.isArray(a)` |

これを使って、型によって条件分岐をすることが出来ます。

```typescript
const healthCheck = (food: Food): string => {
  if (typeof food === "string") {
    return `it's OK`;
  } else {
    return `it's Bad`;
  }
};

console.log(healthCheck(["ramen", "onigiri", "potechi"])); // it's Bad
```

# おわりに

今回はUnionを使って、型を結合してみました！
型を組み合わせて、自分だけのユニークな型を作ってみましょう！

※ **「そういえば、[前回](https://qiita.com/NOMURA_keibyou38/items/06a3218de3ff480ce9de)、Interfaceが出てきたけどtypeと何が違うの...?」**と思った方もいるかもしれません。今後、この違いに関しても書く予定ではあります。が、既に記事があるので一旦こちらにご案内します...! → [TypeScript の Interface と Type Alias の違い](https://qiita.com/sotszk/items/efe32e07e52dce329653)

Next: [TypeScriptをなんとなく理解するための記事③ ~汎用的な型を作成する: Generics~](https://qiita.com/NOMURA_keibyou38/items/45974b8f802c51fe5a1d)

@ ハンズオンも書いたので、さっそく使ってみたい人は是非！
　👉[【TypeScriptハンズオン①】男もすなるTypeScriptといふものを、女もしてみむとてするなり](https://qiita.com/NOMURA_keibyou38/items/8cb285900291df83957a)

# 参考文献
- https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes.html#structural-type-system
- https://typescript-jp.gitbook.io/deep-dive/type-system/typeguard