# 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 泛型 |