# Day 5 - 元組與聯合型別
## 元組
元組是 TypeScript 的一種特殊型別,允許將不同類型的元素儲存在單一陣列內。這於需要將多種數據型別組合在一起時非常有用。
### 特點有
1. 元組陣列長度是固定的
2. 元素順序在宣告時就會被確定
3. 允許不同型別的資料共存
```tsc=
let userInfo: [string, number];
userInfo = ["Alice", 30]; // 正確
userInfo = [30, "Alice"]; // 錯誤:型別對不上
let profile: [string, number] = ['Mary', 18];
function getStudentDetails(studentId: number): [number, string, string] {
// 假設從資料庫獲得學生資訊
return [studentId, "John Doe", "Physics"];
}
const [id, name, course] = getStudentDetails(101);
console.log(`Student ID: ${id}, Name: ${name}, Course: ${course}`);
```
## 元組常見使用時機一:函式返回多個值
當函式需要回傳多個值時,元組是一種非常方便的方式。允許你將多個值組合成一個緊湊的資料結構,並且每個值可以有不同的型別。
```typescript=
function getSize(): [number, number] {
return [width, height];
}
```
## 元組常見使用時機二:解讀 CSV 格式
在解析 csv 資料蠻派得上用場的,因為 csv 的資料通常每筆資料在取值上型別都不相同
**HTML:**
```html=
<!DOCTYPE html>
<html>
<head>
<title>CSV Parser</title>
</head>
<body>
<input type="file" id="file-input" />
<script src="parseCSV.js"></script>
</body>
</html>
```
**parseCSV.ts**
```typescript=
// 元組型別
function parseCsv(content: string): [string, number, string][] {
return content.split("\n").map(line => {
const [name, ageString, position] = line.split(",");
const age = parseInt(ageString, 10);
return [name, age, position];
});
}
function handleFileSelect(evt: any) {
const file = evt.target.files[0];
const reader = new FileReader();
reader.onload = function(event) {
const content = event.target.result as string;
const employees = parseCsv(content);
console.log(employees);
};
reader.readAsText(file);
}
document.getElementById('file-input').addEventListener('change', handleFileSelect, false);
```
**CSV 測試檔:employees.csv,請檔案儲存起來後,在 index.html 的 input file 加入後觸發 change 事件,便可看到 console 的資訊**
```csv=
John Doe,30,Developer
Jane Smith,25,Designer
Max Johnson,40,Manager
Emily Davis,35,Analyst
Alex Brown,28,Tester
```
## 聯合型別
在 TypeScript 中,聯合型別(Union Types)允許一個變數具有多個可能的型別。可增加程式碼的靈活性。
```tsx
// 範例程式碼 1
function printId(id: number | string) {
console.log(`ID: ${id}`);
}
printId(123); // 輸出: ID: 123
printId("abc"); // 輸出: ID: abc
// 範例程式碼 2
function printResult(result: string | number) {
if (typeof result === "string") {
console.log(`Result: "${result}"`);
} else {
console.log(`Result: ${result}`);
}
}
printResult("success"); // 輸出: Result: "success"
printResult(42); // 輸出: Result: 42
```
## 單選題
**題目一:下列哪個選項正確描述了元組?**
- A. 元組是一種無序的資料結構
- B. 元組可以包含不同類型的值
- C. 元組的長度可以動態調整
- D. 元組的元素可以被修改
**題目二:以下哪個描述最準確地表示 TypeScript 中的「聯合型別」?**
- A. 聯合型別是一種將多個不同型別組合成一個型別的方式。
- B. 聯合型別是一種用於表示陣列的型別。
- C. 聯合型別是一種用於表示物件的型別。
**題目三:當我們想要表示多個不同型別的選項,並將它們合併成一個型別,我們應該使用什麼 TypeScript 功能?**
A. 元組
B. 聯合型別
**題目四:以下哪個 TypeScript 寫法表示一個元組(包含姓名和年齡)?**
A.
```tsx
const person: [string, number] = ["John", 30];
```
B.
```tsx
const person: [string] = ["John", 30];
```
C.
```tsx
const person: { name: string; age: number } = { name: "John", age: 30 };
```
D.
```tsx
const person: (string | number)[] = ["John", 30];
```
**題目五:**
以下哪個 TypeScript 寫法表示一個聯合型別(可以是字串或數字)?
A.
```tsx
const value: string = "Hello";
```
B.
```tsx
const value: string | number = "Hello";
```
C.
```tsx
const value: (string | number)[] = ["Hello", 42];
```
D.
```tsx
const value: { text: string } = { text: "Hello" };
```
**題目六:**
以下哪個 TypeScript 寫法表示一個函式參數的型別註釋(接受兩個數字並返回它們的和)?
PS:1/21 更新,調整為「函式參數」
A.
```tsx
const add = (a: number, b: number): number => a + b;
```
B.
```tsx
function add(a: number, b: number) {
return a + b;
}
```
C.
```tsx
const add: (a: number, b: number) => number = (a, b) => a + b;
```
D.
```tsx
const add = (a, b) => a + b;
```
## 開發題
> 建議先看完 **[TypeScript 常用型別](https://courses.hexschool.com/courses/typescript-30/lectures/50717961)** 章節,再來挑戰此題目
請將以下待辦事項 JavaScript 程式碼,改為 TypeScript 版本,可隨意調整程式邏輯,只要確保有完成以下四項即可:
1. 可以新增待辦
2. 可以編輯待辦
3. 可以刪除待辦
4. 點擊待辦時,可以有劃線表示做完
```html=
<!DOCTYPE html>
<html>
<head>
<title>Todo List</title>
</head>
<body>
<h1>Todo List</h1>
<!-- 待辦事項輸入框和按鈕 -->
<input type="text" id="taskInput" placeholder="新增待辦事項">
<button id="addTaskButton">新增</button>
<!-- 待辦事項清單 -->
<ul id="taskList">
<!-- 在這裡顯示待辦事項項目 -->
</ul>
<!-- JavaScript 程式碼 -->
<script>
// 取得 HTML 元素
const taskInput = document.getElementById("taskInput");
const addTaskButton = document.getElementById("addTaskButton");
const taskList = document.getElementById("taskList");
// 儲存待辦事項陣列
const tasks = [];
// 建立新的待辦事項
function createTask(taskText) {
const task = {
text: taskText,
done: false
};
return task;
}
// 更新待辦事項列表
function renderTaskList() {
// 清空現有的清單項目
taskList.innerHTML = "";
// 依次處理每個待辦事項
for (let i = 0; i < tasks.length; i++) {
const task = tasks[i];
// 建立一個待辦 DOM 元素
const listItem = document.createElement("li");
// 檢查是否已完成,如果是,添加完成樣式
if (task.done) {
listItem.classList.add("done");
}
// 顯示待辦事項文字
listItem.textContent = task.text;
// 建立編輯按鈕
const editButton = document.createElement("button");
editButton.textContent = "編輯";
editButton.addEventListener("click", () => {
const editedText = prompt("編輯待辦事項", task.text);
if (editedText !== null) {
task.text = editedText;
renderTaskList();
}
});
// 建立刪除按鈕
const deleteButton = document.createElement("button");
deleteButton.textContent = "刪除";
deleteButton.addEventListener("click", () => {
const confirmDelete = confirm("確定要刪除這個待辦事項嗎?");
if (confirmDelete) {
tasks.splice(i, 1);
renderTaskList();
}
});
// 將編輯和刪除按鈕添加到待辦列表
listItem.appendChild(editButton);
listItem.appendChild(deleteButton);
// 添加點擊事件監聽,切換完成狀態
listItem.addEventListener("click", () => {
task.done = !task.done;
renderTaskList();
});
// 將該待辦添加到待辦列表中
taskList.appendChild(listItem);
}
}
// 新增待辦事項的事件監聽
addTaskButton.addEventListener("click", () => {
const taskText = taskInput.value.trim();
// 確保輸入不為空
if (taskText !== "") {
const task = createTask(taskText);
// 添加待辦事項到陣列中
tasks.push(task);
// 清空輸入框
taskInput.value = "";
// 重新渲染待辦事項清單
renderTaskList();
}
});
// 初始化時渲染待辦事項清單
renderTaskList();
</script>
<!-- CSS 樣式 -->
<style>
.done {
text-decoration: line-through;
}
</style>
</body>
</html>
```
<!-- 解答:
單選題目:B、A、B、A、B、A
-->
回報區
---
| Discord | CodePen / 答案 | 開發題備註 |
|:-------------:|:----------------------------------------------------------------:|:----------------------------------------------------------------:|
|洧杰|[Codepen](https://codepen.io/hexschool/pen/poYgYqW?editors=1010)| 有嘗試用 type、泛型~
|hannahpun|[Codepen](https://codepen.io/hannahpun/pen/LYaRKOL)
|展誠|[Codepen](https://codepen.io/hedgehogkucc/pen/qBvazPm?editors=1010)| 有嘗試用 type、泛型~~
|苡安|[Codepen](https://codepen.io/hedgehogkucc/pen/qBvazPm)| 有嘗試用 type
|ZS|[Codepen](https://codepen.io/irishuang/pen/yLwaddO)|
|77_0411|[Codepen](https://codepen.io/chungchi/pen/jOJMgNb)|
|hannahTW|[Codepen](https://codepen.io/hangineer/pen/LYabPQV?editors=0010)| 有嘗試用 interface~
|Jack|[Codepen](https://codepen.io/lj787448952/pen/gOELOav)|
|YC|[HackMD](https://hackmd.io/SKoJd3EsTlitnjzCx4Rarg)| 有嘗試用 interface |
|nina.kuo|[Codepen](https://codepen.io/ninakuo0814/pen/WNmGXPN)|
|hiYifang|[HackMD](https://hackmd.io/@gPeowpvtQX2Om6AmD-s3xw/B1VlA0_uT)|
|Otis|[Codepen](https://codepen.io/humming74/pen/VwRmLew?editors=1011)|
|Henry_Wu | [Codepen](https://codepen.io/hekman1122/pen/abMBzXR?editors=1010) |有嘗試用 type
|Bryan Chu|[CodePen](https://codepen.io/bryanchu10/pen/mdoOVvd)||
|jasperlu005|[Codepen](https://codepen.io/uzzakuyr-the-reactor/pen/JjzbXGV?editors=1010)|
|Zuo|[Codepen](https://codepen.io/linchinhsuan/pen/XWGNjKg)|有嘗試用 type |
|yunhung|[Codepen](https://codepen.io/ahung888/pen/abMBJgR)| 有嘗試用 type |
|銀光菇|[Codepen](https://codepen.io/genesynthesis/pen/qBvqXwL)| 有嘗試用 type
|Derrick|[Codepen](https://codepen.io/Derricktang/pen/NWJbaQz)|
|薏慈|[Codepen](https://codepen.io/its_wang/pen/VwRmrdr)| 有嘗試用 type
|leave3310|[Codepen](https://codepen.io/leave3310-the-looper/pen/MWxbOPw?editors=0010)| 有嘗試用 type
|BonnieChan|[Codepen](https://codepen.io/Bonnie-chan-the-bold/pen/BabQywy?editors=1010)|有嘗試使用type|
|Lisa|[Codepen](https://codepen.io/lisaha/pen/xxBRPor)|有嘗試使用interface|
|deedee1215 |[Codepen](https://codepen.io/diddy032/pen/XWGNzvp)|有嘗試用type、interface|
|rikku1756 |[Codepen](https://codepen.io/rikkubook/pen/gOELzJb?editors=1011)|有嘗試用type|
|Starr|[CodePen](https://codepen.io/StarrZhong/pen/oNVYyoN)|嘗試使用type, interface|
|m_m|[CodePen](https://codepen.io/minnn7716/pen/yLwVzVK)|嘗試使用 type|
|Teddy|[CodePen](https://codepen.io/TaideLi/pen/QWoGPed)|嘗試使用type, enum,泛型(一點點)|
|wei|[CodePen](https://codepen.io/jweeei/pen/dyrOLmg?editors=1010)|
|Mi|[CodePen](https://codepen.io/Mi-Jou-Hsieh/pen/QWoGpbw?editors=1000)|有嘗試用 interface|
|HsienLu|[CodePen](https://codepen.io/Hsienlu/pen/NWJdGRz)|有嘗試用interface|
|皓皓|[HackMD](https://hackmd.io/@cutecat8110/rkYlwwZF6)|有嘗試用 type|
| 黃士桓 | [codePen](https://codepen.io/shr-huan-huang/pen/BabpzjJ) | 使用type |
|wendy_.li| [HACKMD](https://hackmd.io/PcmFgqZwRd-4Ep3-LgK5_Q) | 使用type |
|shan13| [codePen](https://codepen.io/yishan13-tsai/pen/KKEaqWr) | |
|Amberhh| [codepen](https://codepen.io/Amberhh/pen/rNRjLNb)| 使用 interface|
|連小艾|[Codepen](https://codepen.io/bolaslien/pen/poYRKEw?editors=1010)|使用 type, as|
|JC|[Codenpen](https://codepen.io/jcsamoyed/pen/MWxbYab?editors=0011)|
| Rochel |[Codepen](https://codepen.io/rochelwang1205/pen/MWxJPpO?editors=1010)|
| LinaChen |[Codepen](https://codepen.io/LinaChen/pen/jOJMjYg)|有嘗試用 interface|
| NiuNiu |[Codepen](https://codepen.io/Dawson-the-bold/pen/mdoRLWz?editors=0010)|
erwin阿瀚|[CodePen](https://codepen.io/yohey03518/pen/wvOgVQw?editors=0010)
| clairechang |[Notion](https://claire-chang.notion.site/Day-5-96d412deb68f4680a9749015e07791c6)|interface|
| Alyce |[Codepen](https://codepen.io/alycehwy/pen/yLwgBRq)|有嘗試用type|
| Kai |[Codepen](https://codepen.io/kaiyuncheng-the-styleful/pen/KKEWKeb?editors=1010)|有嘗試用type|
| 神奇海螺|[CodePen](https://codepen.io/ksz54213/pen/GReWZzZ)| 使用 interface|
| 翰毅 |[Codepen](https://codepen.io/yzuigtdw-the-animator/pen/VwRPqMx)|有嘗試用type|
| bonnieli1414 |[Codepen](https://codepen.io/bonnieli1414/pen/mdoWBRZ?editors=0011)||
| fanshu0303 | [CodePen](https://codepen.io/JuiHsuanLee0303/pen/RwdpzRr) ||
| MCBB_4881 |[CodePen](https://codepen.io/ebvaxaah-the-bashful/pen/OJqmJNW?editors=1010)|使用 interface|
|時雨|[CodePen](https://codepen.io/jjustin-35/pen/jOJmEpN?editors=1111)|使用 type, as |
| 精靈 | [CodePen](https://codepen.io/justafairy/pen/wvOeapw) | 有嘗試使用 type, as |
|Snorlax|[HackMD](https://hackmd.io/@snorlaxpock/H1rsvIqFp)|
|小米|[HackMD](https://codepen.io/joanne-wei/pen/wvOdQMo)|使用type
|ethan1331|[CodePen](https://codepen.io/EthanTsai/pen/dyrpmNV)|
|Yoshi|[CodePen](https://codepen.io/yoshiyyc/pen/dyrRyoL)| 有使用 type |
|aki|[codepen](https://codepen.io/aki168/pen/ZEPXavy)|
|zoe|[Codepen](https://codepen.io/Zoechiueh/pen/xxBXJvy?editors=1011)|
|亞當|[Codepen](https://codepen.io/Adam-Hsu/pen/vYPWOvd?editors=0010)|使用 interface|
|Nick Lin|[Codepen](https://codepen.io/NickLinP/pen/RwdLvgL?editors=1111)|使用 type|
|Eileen|[Codepen](https://codepen.io/Eileen-io/pen/YzgeXOG)|使用 type|
|狸貓|[Codepen](https://codepen.io/tanuki320/pen/GRedxpj?editors=0010)|有嘗試使用 type, as|
|Tori|[Codepen](https://hackmd.io/OAdkiOH-S_WkD-LF6IONVA?view)|使用 type、interface、as|
puffy|[Codepen](https://codepen.io/TernMayDay/pen/abMMqrg?editors=1010)|有嘗試使用 type, as
| 我是泇吟 | [Codepen](https://codepen.io/kljuqbxs/pen/VwJNVgz) | 有嘗試使用 type interface 泛型 |