TypeScriptをなんとなく理解するための記事③ ~汎用的な型を作成する: Generics~

# この記事は何？

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

今回は、型の使いまわしである**Generics**について見ていきます。

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

# 型の組み合わせとは？

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

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


※ Unionについては、[前回の記事](https://qiita.com/NOMURA_keibyou38/items/9db230baf556cdfee276)で紹介しています。

# Genericsとは？

TypeScriptにおけるGenerics（ジェネリクス）を学ぶ前に、そもそもGenericsの英単語の意味を確認してみます。

> [genericsとは](https://ejje.weblio.jp/content/generics)
> 一般的な、ジェネリックの、属の、ノーブランド商品

なんだか、定まっていないというか、汎用的な意味合いを感じます。

実際に、TypeScriptにおける、Genericsも同じような意味です。
TypeScriptにおけるGenericsは、**利用されるまで型が確定しない**、クラス, 関数, インターフェイスなどなど...を実現するためのものです。

事前にガッチガチに型定義するのもいいですが、汎用的に使える型もほしいです。
そこで、Genericsが活躍します。

もう少しイメージを掴むために、実際にコードを見ていきます。

まず、今までの知識を使って、関数を作ってみます。

```typescript
// 引数value1, value2は文字列型で、返り値は各要素が文字列の配列
const returnStrArray = (value1: string, value2: string):string[] => {
	return [value1, value2];
};
// 引数value1, value2は数値型で、返り値は各要素が数値の配列
const returnNumberArray = (value1: number, value2: number):number[] => {
	return [value1, value2];
};

const penguinsName = returnStrArray('コウテイペンギン','アデリーペンギン'); // ['コウテイペンギン', 'アデリーペンギン']
const penguinsWeight = returnNumberArray(1000, 50); // [1000, 50]
```

上のコードは、引数`value1`, `value2`を含む配列を返す関数です。
...同じようなことを2回もやるのって冗長じゃないですか...?

そこで、汎用的なことを出来るGenericsを利用します👇

```typescript
const returnArray = <T>(value1: T, value2: T):T[] => {
  return [value1, value2];
}

const penguinsNames = returnArray<string>('コウテイペンギン','アデリーペンギン'); // ['コウテイペンギン', 'アデリーペンギン']
const penguinsWeights = returnArray<number>(1000, 50); // [1000, 50]
```

`T`は何にでも変わる型です。

```typescript
// T → string
const penguinsNames = returnArray<string>('コウテイペンギン','アデリーペンギン');
```

`<string>`のように指定すると、`T`が`string`であることを示します。なので、以下の型を定義した関数と同義になります。

```typescript
const returnArray = (value1: string, value2: string):string[] => {
  return [value1, value2];
}
```

アロー関数でGenericsを利用するときは、`<T>`を`()`の前につけてあげる必要があるため`<T>()`のような形になっています。

このように、Genericsを利用することで汎用的で使いまわし可能な型定義をすることが出来ます。

> TypeScriptにおけるGenericsは、利用されるまで型が確定しない、クラス, 関数, インターフェイスなどなど...を実現するためのものです。

この伏線を回収することが出来たと思います。
`T`は`<string>`のように指定するまで型が確定しないことから、

今回の例では、**利用するまで型が確定しない関数**を実現出来たと思います。

```typescript
const penguinsNames = returnArray<string>('コウテイペンギン','アデリーペンギン'); // 利用したから型が確定
```

他にも、

```typescript
interface funcs<T> {
  add: (obj: T) => void;
  get: () => T;
}
```

みたいに、独自の型を宣言出来たりもします。

# おわりに

できるだけわかりやすく伝えようとしましたが、理解出来そうでしょうか？
この記事だけで理解していただけましたら、是非LGTM✨いただければと思います。

理解できない方がいた場合は...もっとわかりやすく伝えられるよう精進します...!

Next: [TypeScriptをなんとなく理解するための記事④ ~構造型~](https://qiita.com/NOMURA_keibyou38/items/5f1126cd39469f6f9faa)

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

# 参考文献
- https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes.html
- https://blog.mitsuruog.info/2019/03/try-typescript-generics-101
- https://ejje.weblio.jp/content/generics