Section 1:基礎泛型回顧與 Constraints
泛型(Generics)讓函式、介面、Class 可以接受「任意型別」的參數,同時保留型別資訊。 但光是「任意型別」還不夠——很多時候你需要告訴 TypeScript:「T 可以是任何型別,但它必須符合某個形狀」。 這就是 Generic Constraints(泛型約束)的用途。
keyof constraint — 最常見的泛型用法
K extends keyof T 確保你傳入的 key 必定是物件 T 上存在的欄位, 回傳型別也能從 T[K] 精確推導出來:
為什麼不直接用 any? 用 any 等於告訴 TypeScript「不要管這裡的型別」。 泛型讓你在「彈性」和「型別安全」之間取得平衡——函式可以接受多種型別, 但 TypeScript 仍然知道每個位置的具體型別,不會讓你傳錯或取錯欄位。
Section 2:Conditional Types — 型別的 if-else
Conditional Types 讓型別系統擁有「條件判斷」能力,語法和三元運算子一模一樣, 只是操作對象從「值」變成「型別」。
infer 關鍵字 — Conditional Types 的最強功能
infer 讓你在 Conditional Types 的條件判斷中「捕獲」未知的型別, 就像正則表達式中的捕獲組。這是實作 ReturnType、Parameters 等內建 Utility Types 的核心機制:
infer 只能在 extends 子句的右邊使用。它的作用是「讓 TypeScript 去推斷這個位置的型別,並給它一個名字」。 如果條件成立(T extends ...),就可以在 true branch 使用這個名字(R、U、P、E 等)。 如果條件不成立,就進入 false branch,這時候那個名字就不存在了。
Section 3:Mapped Types — 批次轉換型別
Mapped Types 讓你基於現有型別,批次生成新型別。語法像是在「遍歷」型別的所有 key, 並對每個 key 的型別做變換——這就是 TypeScript 所有內建 Utility Types 的實作基礎。
as 重新映射(TypeScript 4.1+)
TypeScript 4.1 加入了 as 子句,讓你在 Mapped Type 中同時改變 key 的名稱:
Section 4:Template Literal Types(模板字串型別)
Template Literal Types(TypeScript 4.1+)讓你用字串模板的語法,從現有的 string literal 型別組合出新的型別。 結合 Mapped Types,可以自動生成大量型別,大幅減少手動維護的工作量。
Section 5:常用 Utility Types 深度解析
TypeScript 內建了許多 Utility Types,多數人只知道「可以用 Partial」,但不知道它是怎麼實作的。 理解原理可以讓你在需要時組合出自己的 Utility Types,而不是只靠記憶。
實用組合:DTO 型別生成
Utility Types 的真正威力在於組合使用。以下是實際後端開發中常見的型別設計:
Section 6:Discriminated Union — 更安全的狀態建模
狀態管理是前端開發最常踩坑的地方之一。Discriminated Union(可辨識聯合)讓每個狀態都是獨立且完整的, TypeScript 可以精確地在每個分支推導出正確的型別,消除「狀態不一致」的 bug。
| 技術 | 常見用途 |
|---|---|
| Generic Constraints | API 工具函式、React Hooks(useLocalStorage、useFetch) |
| Conditional Types | 型別工具函式、infer 提取函式回傳型別 / Promise 內層型別 |
| Mapped Types | DTO 轉換(Partial / Required)、Readonly 包裝、過濾 key |
| Template Literal | 路由型別、Event Handler 名稱、CSS 值約束 |
| Discriminated Union | 狀態機、API Response 建模、Redux action 型別 |
| Utility Types | 每天都在用,要背起來(Partial、Pick、Omit、Record 最常見) |
從「加冒號」到型別工程師的分水嶺
初級:會用 interface、type、基本 generics,讓 TypeScript 不報紅線
中級:會用 Utility Types(Partial、Pick、Omit),設計合理的 DTO 型別,用 Discriminated Union 建模狀態
進階:能用 Conditional Types + infer 設計型別工具函式,用 Mapped Types + Template Literal 自動生成大量型別,型別系統本身就是文件