4歳娘「パパ、具体的な名前をつけないで？」

↓新作もよろしくやで！

+ [**ジェネリクスをもう少しだけ使いこなす。**](https://qiita.com/Yametaro/items/2e28a7b813dc99c664e9)
+ [**コロナウィルス対策でリモートワークしてみたらReduxやVuexのメリットが分かった**](https://qiita.com/Yametaro/items/c2ecc27185c85bebfeb0)


## 36歳ザコーダーの休日
ワイ「何やこのコード、全然動かへんやん」
ワイ「怖いな～怖いな～…なんか嫌だなあ～」

よめ太郎「（何で自分が書いたコード見て**稲川淳二みたいに怯えとんねん・・・**）」
よめ太郎「（そんな鳥肌立つようなクソコード書いてんのかいな・・・）」

娘（**4歳**）「ねぇ、パパ」

ワイ「なんや、娘ちゃん」

娘「ちょっと、**作ってほしい関数**があるの」

ワイ「またかいな」
ワイ「娘ちゃんはホンマに**関数が大好き**やなぁ」
ワイ「しゃあない、パパはプログラミング苦手やけど、頑張って作ったるわ」

娘「ありがとう、パパ」

## 今回の要件
ワイ「ほんで、今回はどんな関数を作ればええんや？」

娘「えっとね」
娘「`'あ'`という文字列を渡したら」
娘「`['あ', 'あ', 'あ']`という配列を返してくれる」
娘「そんな関数が欲しいの」

ワイ「そんなん何に使うんや・・・」

娘「その関数がなくて、**友達が困ってるの**」

ワイ「**何やて！？**」
ワイ「娘ちゃんの友達が！？」
ワイ「よっしゃ、もう細かい事情なんて聞いたりせん！」
ワイ「ワイが関数を書いたる！」

娘「ワ〜イ！」

ワイ「ワ〜イ！」

## ただし
娘「ただし、間違って文字列以外のものを渡せないように」
娘「ちゃんと**TypeScript**で書いてね」
娘「パパ、TypeScript書ける？」

ワイ「**理論上は可能や**」
ワイ「QiitaでたまにTypeScriptの記事を読んどるからな」

## 実装開始
ワイ「ええと、作るべき関数は・・・」

>`'あ'`という文字列を渡したら、
`['あ', 'あ', 'あ']`という配列を返してくれる。

ワイ「↑これやったな」
ワイ「**1つの文字列**を受け取ったら」
ワイ「その文字列を**3つ詰めた配列**を返せばええんやから・・・」

```typescript
function stringToArray(str) {
  return [str, str, str];
}
```

ワイ「↑こんな感じやろ！」

よめ太郎「**型**が書いてないやん」
よめ太郎「娘ちゃん、さっき『型をつけて』って言うてたで」

ワイ「おお、せやったわ」
ワイ「ちゃんと**TypeScript**で書かな」

よめ太郎「ちなみに、TypeScriptの環境構築は**やっておいたで！**」

ワイ「おお、流石よめ太郎や！」

## TypeScriptで書き直す
ワイ「ええと」
ワイ「引数`str`は**文字列**、つまり**string型**やから」
ワイ「`(str: string)`って書けばええな」
ワイ「戻り値は、**文字列が入った配列**やから・・・」
ワイ「`string[]`やな」
ワイ「せやから・・・」

```typescript
function stringToArray(str: string): string[] {
  return [str, str, str];
}
```

ワイ「↑こうや！」

## できた
ワイ「娘ちゃん、関数できたで！」
ワイ「これで友達も助か・・・」

娘「**パパ、要件が増えちゃったの**」

ワイ「（どどどういうこと・・・？）」

娘「さっきの関数に、**数値も渡せるように**してほしいの」
娘「**友達が困ってるの**」

ワイ「わ、分かったで・・・」

## 数値も渡せるようにしたい

ワイ「ええと」
ワイ「`文字列型 または 数値型`っていうのは」
ワイ「確か`string | number`っていう風に表すんやったな」
ワイ「せやから」

```typescript
function stringToArray(str: string | number): (string | number)[] {
  return [str, str, str];
}
```

ワイ「こうや！」

ワイ「あれ、もう`stringToArray`いう関数名はおかしいな」
ワイ「**string型**だけやなくて**number型**も受け取るもんな」
ワイ「関数名は`stringOrNumberToArray`にしとこか」

ワイ「引数名も`str`じゃなくて」
ワイ「`strOrNum`にしとこか」

```typescript
function stringOrNumberToArray(strOrNum: string | number): (string | number)[] {
  return [strOrNum, strOrNum, strOrNum];
}
```

ワイ「できたで！娘ちゃん！」

## 娘ちゃんによるレビュー

娘「うーん、ちょっと微妙かな」

ワイ「え、何で・・・」

娘「ううんと・・・」

> **文字列型か数値型**の引数を受け取って
**文字列か数値**の配列を返す

娘「↑こういう型付けになっちゃってるから」

> **文字列型**の引数を受け取って
> **数値の配列**を返す

娘「↑こんな実装をしてても、**型チェックを通っちゃうの**」
娘「**文字列**を受け取ったのに、**数値の配列**を返すようなコードを**間違って書けてしまう**・・・」
娘「そんな**隙ができちゃうの**」

ワイ「ホンマや・・・」
ワイ「しかも・・・」

```typescript
  return [1, 'あ', 3];
```

ワイ「↑こんな感じで文字列や数値が**混じってるような**実装してても**型エラーにならへん**やん」
ワイ「これは微妙やな・・・」
ワイ「**文字列**を受け取ったときは**文字列だけの配列**を返したいんやもんな」
ワイ「**引数と同じ型の配列を返す**こと・・・」
ワイ「それを**保証する**にはどうしたらええんや・・・」

娘「よく考えてみてね」
娘「あとね、パパ」
娘「こんなときに言いにくいんだけど・・・」

## またも要件追加
娘「引数として、**オブジェクト**と**数値の配列**も許可して欲しいの・・・」

ワイ「**ぐぬぬ**」
ワイ「（本格的に詰んできたわ・・・）」

## とにかくやってみる

ワイ「`文字列`または`数値`または`オブジェクト`または`数値の配列`・・・・」
ワイ「もう**any**型でええやろ」

よめ太郎「ごめん、あかんわ」
よめ太郎「環境構築したときに**ESLint**の設定をしたんやけど」
よめ太郎「**anyは禁止**にしてもうたわ」

ワイ「**ぐぬぬぬぬぬ**」

よめ太郎「それに、anyを使うと」
よめ太郎「数値を受け取ったのにオブジェクトの配列を返す、とか」
よめ太郎「どんな実装してても**何の型エラーにもならへん**」
よめ太郎「静的型付言語のメリットなくなってまうわ」
よめ太郎「つまり、さっきよりも更にダメになってまうわ」

ワイ「せやな・・・」
ワイ「**引数と同じ型の配列を返す**ことを**型で保証**せなあかんのやもんな・・・」

## こんな機能があったらいいのにな
ワイ「もう、`(string | number | object | number[])`とか書くのダルいし」
ワイ「**引数と同じ型の配列を返す**ことも**型で保証**したいから」
ワイ「関数を呼び出すときに**型を指定**できたらええのになぁ」

> 今回はこの関数に、**文字列を渡して使いまっせ！**

ワイ「↑こんな感じにしたいんや」
ワイ「つまり、関数を呼び出すときに、引数として**型も渡す**」
ワイ「そんな機能があったらいいのになあ・・・」

娘（**4歳**）「**あるよ**」

ワイ「ファッ！？」

娘「**ジェネリクス**を使えばいいんだよ」
娘「普通、関数を呼び出すときは・・・」

```typescript
const stringArray = stringToArray('あ');
```

娘「↑こんな感じで呼び出すけど」
娘「ジェネリクスを使って・・・」

```typescript
const stringArray = stringToArray<string>('あ');
```

娘「↑こう書いてあげればいいんだよ」

ワイ「おお・・・！」
ワイ「`<string>`の部分で**型を渡す**んやな・・・！」

娘「そう」

ワイ「でも、関数を定義している部分にも何か」
ワイ「その**型引数を受け取る**ってことを書かないとあかんのやろ？」

娘「そうだよ」
娘「だから・・・」

```typescript
function stringToArray<T>(str: T): T[] {
  return [str, str, str];
}
```

娘「↑こんな感じだね」

ワイ「なるほどな」
ワイ「`stringToArray<T>`の」
ワイ「`<T>`の部分で**型**を受け取ってるんやな」
ワイ「ほんで、引数部分が`(str: T)`ってことは・・・」

> 引数`str`は`T型`でっせ！

ワイ「ってことかぁ」
ワイ「今回の例だと`T`には`string`が入ってくるから・・・」

> 引数`str`は`string型`でっせ！

ワイ「ってことになるんやな」
ワイ「ほんで、返り値の部分は`T[]`って書いてあるから」

> 返り値は`T型`の値が入った配列でっせ！

ワイ「つまり」

> 返り値は`string型`の値が入った配列でっせ！

ワイ「ってことになるんやな」
ワイ「これなら、**引数と同じ型の配列を返す**ことを**型で保証**できるな！」

娘「うん、あとね」
娘「戻り値の配列の**要素数**を間違えて」
娘「**4個**とか**5個**とかで実装してしまわないように」
娘「戻り値の型は`T[]`より`[T, T, T]`にした方がいいね」

ワイ「おお、そんな型の書き方もあるんやな」
ワイ「**要素数が3個の配列**ってとこまで型で保証できるんやね」
ワイ「ワイ、たまに**間違って**100個詰めちゃう癖があるから助かるわ」
ワイ「娘ちゃん、ありがとうやで！」


## ジェネリクス完全理解ワイ
ワイ「ほな、ジェネリクスを使って」
ワイ「さっきの関数を完成させていくで！」

ワイ「ええと、この関数は」
ワイ「引数として、`文字列`または`数値`または`オブジェクト`または`数値の配列`を受け取れるわけやから」
ワイ「関数名は`stringToArray`やなくて、単に`toArray`にしておこか」
ワイ「引数も`str`じゃなくて単に`arg`にしとくわ」
ワイ「**型引数**は、**何らかの型が入って来る**ってことが分かりやすいように」
ワイ「`SomeType`っていう名前にしておこか！」

```typescript
function toArray<SomeType>(arg: SomeType): [SomeType, SomeType, SomeType] {
  return [arg, arg, arg];
}
```

ワイ「↑こうやな！」

## 実際に関数を使うときは

### 文字列を渡す場合
```typescript
const array = toArray<string>('あ');
```

### 数値を渡す場合
```typescript
const array = toArray<number>(3);
```

### オブジェクトを渡す場合
```typescript
const array = toArray<object>({hoge: 1});
```

### 配列を渡す場合
```typescript
const array = toArray<number[]>([0, 1, 2]);
```

ワイ「↑こんな感じで**型を指定しながら**関数を呼び出せばええんやな！」

よめ太郎「せやな」
よめ太郎「ちなみにそれくらいシンプルな例なら・・・」

```typescript
const stringArray = toArray('あ');

const numberArray = toArray(3);

const objectArray = toArray({hoge: 1});

const arrayArray = toArray([0, 1, 2]);
```

よめ太郎「↑こんな感じで、**型引数を渡さなくても**問題なく呼び出せるで」
よめ太郎「TypeScriptのコンパイラちゃんが・・・」

> コンパイラ「お、今回の引数は**数値**・・・つまり**number型**やな！」

よめ太郎「↑こんな感じで引数の型を**推論**してくれるからな」
よめ太郎「ほんで・・・」

> コンパイラ「ほな、関数が返す値の型は`[number, number, number]`やな！」
コンパイラ「`[number, number, number]`型以外の値を返そうとしてたら、エラーにせんとな！」

よめ太郎「ってな感じでチェックしてくれるねん」

ワイ「なるほどな〜」

## とにかく完成した
ワイ「娘ちゃん！」
ワイ「遂にできたで！！！」

娘「パパ、**余計なことしないで？**」

ワイ「**ファッ！！！？？？**」

娘「つまり」
娘「型引数に**具体的な名前をつけないで？**」

ワイ「`SomeType`のこと・・・？」
ワイ「何でなん・・・？」

## 抽象的すぎるやん

ワイ「`T`とか**抽象的すぎる**やん・・・」
ワイ「もっと、**何らかの型が入って来る**ってことが伝わるような」
ワイ「**具体的**な名前の方がええやん・・・」

娘「**何らかの型**っていう、**すごく抽象的なもの**を表す名前なんだから」
娘「**むしろ抽象的な名前がいい**んだよ」

ワイ「でもさぁ、**何らかの型**なんやから」
ワイ「それを説明するための名前として」
ワイ「`SomeType`とかさ・・・」

娘「いや、`<>`の中には**何らかの型が入って来る**って決まってるんだから」
娘「その**何らかの型ですよ**っていう説明、要る？」
娘「`<T>`を見たら分かるじゃん」
娘「パパは、ペットの犬に`マイドッグ`って名前をつけるの？」
娘「それに、`SomeType`だって結局すごく**抽象的**じゃない？」
娘「ならもう`T`でよくない？」

ワイ「ぐぬぬぬぬ・・・・」
ワイ「・・・**ほな最初から自分で作れや！！！**」

よめ太郎「**（それはたしかに）**」

**〜おしまい〜**

## 新作もよろしくやで！
+ [**ジェネリクスをもう少しだけ使いこなす。**](https://qiita.com/Yametaro/items/2e28a7b813dc99c664e9)
+ [**コロナウィルス対策でリモートワークしてみたらReduxやVuexのメリットが分かった**](https://qiita.com/Yametaro/items/c2ecc27185c85bebfeb0)