【TypeScript入門】ジェネリック型とポリモーフィズム

# まとめ
* ジェネリック型を使うと、同じ型の構造を持ったものをまとめることができる
* まとめることで（共通化する）と保守性が上がり、再利用ができる

## ジェネリック型
* 型を抽象化することができる

###　ジェネリック型パタメーター
* 型をパラメーター化(後から実パラメーターを渡す)
* T,U,V,Wなどがよく使われる

**ジェネリック型を使わない場合、下記のコードのようにstringReduce（）とnumberReduce()は、別々に型エイリアスを書く必要がある。**

```typescript:ジェネリック型を使わない場合

  // 型エイリアスを作るとしたら...？
  type StringReduce = {
    (array: string[], initialValue: string): string
  }

  type NumberReduce = {
    (array: number[], initialValue: number): number
  }

  const stringReduce: StringReduce = (array: string[], initialValue: string): string => {
    let result = initialValue
    for (let i = 0; i < array.length; i++) {
      const item = array[i]
      result += item
    }
    return result
  }
  console.log('Generics basic sample 1:', stringReduce(['I ', 'am ', 'engineer', '.'], ''))
  // Generics basic sample 1: I am engineer.

  const numberReduce: NumberReduce = (array: number[], initialValue: number): number => {
    let result = initialValue
    for (let i = 0; i < array.length; i++) {
      const item = array[i]
      result += item
    }
    return result
  }
  console.log('Generics basic sample 2:', numberReduce([100, 200, 300], 1000))
  // Generics basic sample 2: 1600


```

**ジェネリック型を使った場合、型エイリアスをまとめることができる**

```typescript:ジェネリック型を使った場合
// ジェネリック型でまとめる
  type GenericReduce<T> = {
    (array: T[], initialValue: T): T
  }

  // ジェネリック型を使った呼び出し
  const genericStringReduce: GenericReduce<string> = (array, initialValue) => {
    let result = initialValue
    for (let i = 0; i < array.length; i++) {
      const item = array[i]
      result += item
    }
    return result
  }
  console.log('Generics basic sample 3:', genericStringReduce(['I ', 'am ', 'engineer', '.'], ''))
//Generics basic sample 3: I am engineer.

  const genericNumberReduce: GenericReduce<number> = (array, initialValue) => {
    let result = initialValue
    for (let i = 0; i < array.length; i++) {
      const item = array[i]
      result += item
    }
    return result
  }
  console.log('Generics basic sample 4:', genericNumberReduce([-100, -200, -300], 1000))
//Generics basic sample 4: 400
```

### いろいろなジェネリック型の定義方法

```typescript
    // 完全な呼び出しシグネチャ（個々のシグネチャにジェネリック型を割り当てる）
    type GenericReduce2 = {
      <T>(array: T[], initialValue: T): T
      <U>(array: U[], initialValue: U): U
    }
    // 呼び出しシグネチャの省略記法
    type GenericReduce3<T> = (array: T[], initialValue: T) => T
    type GenericReduce4 = <T>(array: T[], initialValue: T) => T
```

### ジェネリック型のパラメーターを２つ使ってみる

```typescript
  // map関数のシグネチャ
  type Map<T, U> = (array: T[], fn: (item: T) => U) => U[]

  const mapStringsToNumbers: Map<string, number> = (array, fn) => {
    const result = []
    for (let i = 0; i < array.length; i++) {
      result[i] = fn(array[i])
    }
    return result
  }

  const numbers = mapStringsToNumbers(['123', '456', '789'], (item) => Number(item))
  console.log('Generics advanced sample 1:', numbers)
// Generics advanced sample 1: [123, 456, 789]

  const mapNumbersToStrings: Map<number, string> = (array, fn) => {
    const result = []
    for (let i = 0; i < array.length; i++) {
      result[i] = fn(array[i])
    }
    return result
  }

  const strings = mapNumbersToStrings(numbers, (item) => String(item))
  console.log('Generics advanced sample 2:', strings)
  // Generics advanced sample 2:["123", "456", "789"]
```

# ポリモーフィズム
* 多能性・多相性＝いろいろな形に変化できること
* ジェネリック型を用いると
    * 型を抽象化して共通化できる
    * 呼び出すときに具体的な方を渡す
    * 呼び出すことを```型をバインド```するという