# 🏅 Day 11 - 什麼是泛型?
## 回顧之前陣列設定型別的方式
例如:
1. `number[]` 表示一個數字型別陣列
2. `string[]` 表示一個字串型別的陣列。
```=tsx
let numbers: number[] = [1, 2, 3];
let strings: string[] = ["hello", "world"];
```
除此之外,還有哪些定義方式呢?
## 陣列泛型(Array Generic)
此時也可以使用陣列泛型 `Array<元素型別>`,來達成一樣的效果:
```=tsx
let numbers: Array<number> = [1, 2, 3];
let strings: Array<string> = ["hello", "world"];
```
這兩種方式都有符合一樣的效果,下方我們再寫個範例,主要是提供一個字串陣列,並單純回傳這個字串陣列,兩個效果也是一樣的,只是格式不同而已,一個是 **`Array<string>`** 另一個是 **`string[]`**。
### 範例一:**`Array<string>`**:
```tsx
function processStringArray1(arg: Array<string>): Array<string> {
return arg;
}
let stringArray1: Array<string> = ["apple", "banana", "cherry"];
processStringArray1(stringArray1); // 輸出: ["apple", "banana", "cherry"]
```
### 範例二:**`string[]`**:
```tsx
function processStringArray2(arg: string[]): string[] {
return arg;
}
// 使用這個函式
let stringArray2: string[] = ["apple", "banana", "cherry"];
processStringArray2(stringArray2); // 輸出: ["apple", "banana", "cherry"]
```
## 開始進入重頭戲,泛型(Generics)!
泛型(Generics)是一種在定義函式、介面或類別時,不先確定具體的型別,而是在實際使用時,再指定型別的特性。
```=tsx
// `T` 是型別參數(Type Parameter),可代進任意輸入的型別。
function hello<T>(data:T){
console.log(data)
}
hello<string>("Jack")//Jack,data 參數型別會被代入為 String
hello<string>(123) //會出錯,型別錯誤
hello<number>(123)//123,data 參數型別會被代入為 number
```
上面的範例,我在函式名稱 `hello` 後添加了 `<T>`,裡面的 `T` 是**型別參數(Type Parameter)**,可以用來代入任意型別。
這個 `T` 也可以叫做其它名字,例如 `U`,下面程式碼也具備相同功能
```tsx=
//型別參數改為 U
function hello<U>(data:U){
console.log(data)
}
hello<string>("Jack")//Jack,data 參數型別會被代入為 String
hello<string>(123) //會出錯,型別錯誤
hello<number>(123)//123,data 參數型別會被代入為 number
```
通常你在看其它範例,約定俗成會用 `T` 當作型別參數的原因, 主因是 `T` 是 type(型別) 縮寫關係
### 泛型函式 return
當然這個型別參數,也能應用在 `return` 上
```=tsx
// return 也用到了型別參數
function hello<T>(data:T): T{
return data;
}
hello<string>("Jack")//回傳 Jack
hello<string>(123) //會出錯,型別錯誤
hello<number>(123)//回傳 123
```
### 可以有多個型別參數
```tsx=
function callFun<T, U>(e1: T, e2: U): [U, T] {
return [e2, e1];
}
// 推薦:可以使用型別推論寫法
const a = callFun("world", 123);
console.log(a); // [123, "world"]
// 也可以使用型別註釋
const b = callFun<string,number>("world", 123);
console.log(b); // [123, "world"]
// 故意出錯的型別註釋
const c = callFun<string,string>("world", 123);
console.log(c); // [123, "world"]
```
## 問題來了,如果是這樣呢?
```js=
function processStringArray(strings: string[]): string[] {
// ... 一些對字串陣列的操作
return strings;
}
function processNumberArray(numbers: number[]): number[] {
// ... 一些對數字陣列的操作
return numbers;
}
```
看起來兩個函式有一個共通之處,那就是函式參數、return 的型別都一樣,有辦法透過泛型優化嗎?
### **重構為泛型函式**
我們可以將這些函式重構為一個泛型函式,能夠接受任何型別的陣列。泛型 **`T`** 代表陣列中的元素型別。
```tsx
function processArray<T>(arr: T[]): T[] {
return arr;
}
let strAry = ["apple", "banana", "cherry"];
let processedStrings = processArray<string>(strAry);
let numberAry = [1, 2, 3];
let processedNumbers = processArray<number>(numberAry);
```
在這個重構後的範例中,**`processArray`** 函式使用泛型 **`T`** 來表示陣列元素的型別。當你呼叫這個函式時,可以明確指定這個型別,如 **`processArray<string>`** 或 **`processArray<number>`**。
這樣你就能夠用同一個函式來處理多種型別的陣列,藉此來提升代碼的簡潔性。
## 泛型圖解
以此範例程式碼為例子,下方繪製幾張流程圖,幫助大家吸收更順利 🙌
```=tsx
function hello<T>(data:T): T{
return data;
}
hello<string>("Jack")//Jack,data 參數型別會被代入為 String
hello<string>(123) //會出錯,型別錯誤
hello<number>(123)//123,data 參數型別會被代入為 number
```
### 泛型函式生成

### 泛型執行步驟

# 開發題
## 題目一:建立泛型字串陣列
### 函式名稱
`createGenericStringArray`
### 輸入
兩個字串 `str1` 和 `str2`。
### 輸出
一個泛型陣列 `Array<string>`,包含 `str1` 和 `str2`。
### 範例
輸入`"hello"` 和 `"world"`,函式回傳陣列為 `["hello", "world"]`。
### 程式碼線索
```tsx=
function createGenericStringArray(str1: <設定型別>, str2: <設定型別>): <設定回傳型別> {
return <回傳格式>;
}
// 使用這個函式
const stringArray = createGenericStringArray("hello", "world");
console.log(stringArray); // 輸出: ["hello", "world"]
```
## **題目二:泛型函式**
練習泛型 `<T>` 用法
### **函式名稱**
**`identity`**
### **輸入**
一個型別參數 **`value`**。
### **輸出**
直接回傳輸入的 **`value`**。
### **範例**
輸入一個數字 **`5`**,函式回傳 **`5`**;輸入一個字串 **`"hello"`**,函式回傳 **`"hello"`**。
### **程式碼線索**
```tsx=
// 補上型別參數
function identity(value):? {
return value;
}
// 使用這個函式
const number = identity(5);
console.log(number); // 輸出: 5
const string = identity("hello");
console.log(string); // 輸出: "hello"
```
## 題目三:元組元素交換
### 函式名稱
**`swapElements`**
### 輸入
一個包含兩個不同型別元素的元組(Tuple),例如 **`["hello", 10]`**。
### 輸出
元素位置交換後的新元組,例如 **`[10, "hello"]`**。
### 範例
輸入元組 **`["hello", 10]`**,函式回傳的元組為 **`[10, "hello"]`**。
### 程式碼線索
```tsx=
function swapElements(){
return ;
}
// 使用這個函式
const swappedTuple = swapElements(["hello", 10]);
console.log(swappedTuple); // 輸出: [10, "hello"]
```
## **題目四:使用泛型處理不同型別的陣列**
### **函式名稱**
**`processArray`**
### **輸入**
- 一個泛型陣列 **`array: Array<T>`**,其中 **`T`** 可以是 **`string`**、**`number`** 或 **`boolean`**。
- 一個泛型函式 **`process: (item: T) => T`**,用於對陣列中的每個元素進行處理。
### **輸出**
一個經過處理的泛型陣列 **`Array<T>`**,包含經過函式 **`process`** 處理過的所有元素。
### **範例**
1. 輸入字串陣列 **`["apple", "banana"]`** 和一個將每個字串轉為大寫的函式,函式回傳陣列為 **`["APPLE", "BANANA"]`**。
2. 輸入數字陣列 **`[1, 2, 3]`** 和一個將每個數字加倍的函式,函式回傳陣列為 **`[2, 4, 6]`**。
3. 輸入布林陣列 **`[true, false, true]`** 和一個將每個布林值取反的函式,函式回傳陣列為 **`[false, true, false]`**。
### **模擬程式碼**
```tsx=
function processArray(array, process){
return ;
}
// 使用這個函式
const processedStrings = processArray(["apple", "banana"], (s) => s.toUpperCase());
console.log(processedStrings); // 輸出: ["APPLE", "BANANA"]
```
## 回報流程
將答案寫在 CodePen,並貼至底下回報就算完成了喔!
解答位置請參考下圖(需打開程式碼的部分觀看)

<!-- 解答:
-->
回報區
---
| Discord | CodePen / 答案 |
|:-------------:|:----------------------------------------------------------------:|
|洧杰|[Codepen](https://codepen.io/hexschool/pen/poYgYqW?editors=1010)|
|hannahpun|[Codepen](https://codepen.io/hannahpun/pen/ZEPyRJp?editors=0011)|
|LinaChen|[Codepen](https://codepen.io/LinaChen/pen/WNmOyZN)|
|苡安|[Codepen](https://codepen.io/yi-an-yang/pen/bGZRjbE)|
|精靈|[CodePen](https://codepen.io/justafairy/pen/vYPZaZB)|
|m_m|[CodePen](https://codepen.io/minnn7716/pen/JjzWqQz)|
|展誠|[CodePen](https://codepen.io/hedgehogkucc/pen/YzgQvVv?editors=1012)|
|Amberhh | [codepen](https://codepen.io/Amberhh/pen/wvOexVq?editors=0011)|
|77_0411| [CodePen](https://codepen.io/chung-chi/pen/dyrRqbY?editors=1011)|
|Henry_Wu|[Codepen](https://codepen.io/hekman1122/pen/vYPZzPW?editors=0010)|
|HsienLu|[CosePen](https://codepen.io/Hsienlu/pen/poYPwaK)|
|clairechang|[Notion](https://claire-chang.notion.site/Day-11-ec326e552d4148b8abdec5b8790fbd93)|
|hannahTW|[codepen](https://codepen.io/hangineer/pen/NWJgBEv?editors=1011)|
|Lisa|[codepen](https://codepen.io/lisaha/pen/RwdgOpp?editors=1012)|
|wendy_.li|[HACKMD](https://hackmd.io/PcmFgqZwRd-4Ep3-LgK5_Q)|
|Bryan Chu|[CodePen](https://codepen.io/bryanchu10/pen/mdowYVK)|
|jasperlu005|[Codepen](https://codepen.io/uzzakuyr-the-reactor/pen/KKEqLNK?editors=1011)|
|deedee1215|[Codepen](https://codepen.io/diddy032/pen/gOERmmX)|
|Mi|[Codepen](https://codepen.io/Mi-Jou-Hsieh/pen/NWJgmaz?editors=1011)|
|yunhung|[Codepen](https://codepen.io/ahung888/pen/JjzyoeK?editors=0011)|
|Kai|[Codepen](https://codepen.io/kaiyuncheng-the-styleful/pen/bGZrVWe?editors=0011)|
|連小艾|[Codepen](https://codepen.io/bolaslien/pen/YzgxWyB?editors=0011)|
|雙魚|[Codepen](https://codepen.io/emiarcak/pen/RwdZRxb?editors=0012)|
|hiYifang|[HackMD](https://hackmd.io/@gPeowpvtQX2Om6AmD-s3xw/r1dPCijta)|
|JC|[Codepen](https://codepen.io/jcsamoyed/pen/PoLjXqm?editors=0012)|
|Alyce|[Codepen](https://codepen.io/alycehwy/pen/YzgQOZp)|
|翰毅|[Codepen](https://codepen.io/yzuigtdw-the-animator/pen/LYajxpJ?editors=1111)|
|YC|[HackMD](https://hackmd.io/SKoJd3EsTlitnjzCx4Rarg)|
|皓皓|[HackMD](https://hackmd.io/@cutecat8110/ry93J23YT)|
|erwin阿瀚|[CodePen](https://codepen.io/yohey03518/pen/vYPJpqJ?editors=1010)
|Teddy|[CodePen](https://codepen.io/TaideLi/pen/RwdZMaO)
|BonnieChan|[CodePen](https://codepen.io/Bonnie-chan-the-bold/pen/jOJLZpE?editors=0011)
|wei|[codePen](https://codepen.io/jweeei/pen/bGZraNR?editors=1011)|
|Starr|[codePen](https://codepen.io/StarrZhong/pen/qBvXzbY)|
|wei|[codePen](https://codepen.io/jweeei/pen/bGZraNR?editors=1011)|
|Otis|[codePen](https://codepen.io/humming74/pen/NWJaNeZ?editors=1012)|
|shan13|[codePen](https://codepen.io/yishan13-tsai/pen/MWxEezE)|
|rikku1756|[codePen](https://codepen.io/rikkubook/pen/zYbEPaR?editors=1111)|
|銀光菇|[codePen](https://codepen.io/genesynthesis/pen/YzgEyza)|
|薏慈|[CodePen](https://codepen.io/its_wang/pen/BabmoxB)|
|神奇海螺|[CodePen](https://codepen.io/ksz54213/pen/eYXePgoL)|
|Snorlax|[HackMD](https://hackmd.io/@snorlaxpock/r1IRG3iK6)|
|leave3310|[HackMD](https://codepen.io/leave3310-the-looper/pen/BabVRZa?editors=0011)|
|Tori|[HackMD](https://hackmd.io/OAdkiOH-S_WkD-LF6IONVA?view)|
|我是泇吟|[Codepen](https://codepen.io/kljuqbxs/pen/rNEgqKv)|