【TypeScript 小教室 03】 接續上一篇內容:[什麼是型別防衛敘述 (type guard)](https://hackmd.io/@flag23311033/rJDpwuGDt)? 要解釋型別防衛敘述,我們要先從 TypeScript 提供的一個功能──型別聯集 (type union) 說起。 * * * 若把 TypeScript 的型別保護機制想像成一道光譜, 其中一端就是絕對自由的 any 型別, 而另一端則是只准使用單一型別的嚴格型別註記。不過在這兩個極端之間, TypeScript 提供了所謂的型別聯集, 允許你用一個型別來接納多種型別。底下的範例便定義了一個可傳回不同資料型別的函式, 並使用型別聯集為其進行註記: function calculateTax(amount: number, format: boolean): string | number calculateTax() 函式的傳回值是 string 與 number 這兩種型別的聯集, 代表它可以是 string 或者 number... 要特別注意的是, TypeScript 會將型別聯集視為一個獨立的型別, 而它可以呼叫的方法就是其中所有型別的交集 ( 意即, 只有每個型別都共同具備的方法, 才能在型別聯集使用)。這代表即使 calculateTax() 傳回 number, 函式的傳回值以及 taxNumber 變數的推論型別都是『 string | number』 而非只是 number。 ---摘錄至 《[TypeScript 邁向專家之路](https://www.books.com.tw/products/0010906604)》Ch.7 * * * 換句話說,就算 calculateTax() 函式的傳回值是 string 或 number,這個值實際上會變成 string | number 聯集型別。而當我們想要把這個值重新當成 string 或 number 型別操作時,可以使用型別斷言 (type assertion): let taxNumber = calculateTax(100, false) as number; let taxString = calculateTax(100, true) as string; 問題在於,型別斷言並不會做型別轉換,它只是在告訴 TypeScript 編譯器:聽好,老子說這是 number 就是 number!但這樣不能保證值本身的型別真的和你認定的一樣。要是你呼叫值的某個方法,值的型別卻搞錯了,這種錯誤就會等到實際執行才引爆。 在這種時候,型別防衛敘述就派上用場了: * * * 型別斷言固然方便, 但無法確保值本身的型別符合斷言指定的型別。為了確保操作上的安全, 我們可利用條件敘述結合 typeof 關鍵字來檢測一個值是否為特定基本型別, 並藉此將之限縮到該型別。這種機制稱為型別防衛敘述: let taxValue = calculateTax(100, false); // 型別防衛敘述 if (typeof taxValue === "number") { console.log(`Number Value: ${taxValue.toFixed(2)}`); } else { console.log(`String Value: ${taxValue.charAt(0)}`); } --- 摘錄至《[TypeScript 邁向專家之路](https://www.books.com.tw/products/0010906604)》Ch.7 * * * TypeScript 編譯器會知道,if 區塊中只有 taxValue 為 number 型別時才能執行,所以這區塊內的 taxValue 會自動被「限縮」為 number 型別。反之,else 區塊內的 taxValue 一定只會是 string,故此區塊的值會變成 string 型別。 藉由型別防衛敘述,我們就可以在程式中保留 JavaScript 能對變數賦予多種型別的彈性、但在操作時仍然確保其型別安全,減少在執行階段引發非預期錯誤的機會。 TypeScript 的型別防衛敘述並不限於 if...else,它同樣適用於 switch...case。而且 TypeScript 提供的型別機制更包括但不限於以下功能: ‧unknown 與 never 型別 ‧用編譯器選項 strictNullChecks 禁止將 null 與 undefined 指派給值 ‧非 null 值斷言 (non-null assertion) ‧明確賦值斷言 (definitive assignment assertion) ‧函式的型別多載 (type overloading) ‧型別別名 (type alias) ‧字面值型別 (literal value type) ‧型別交集 (type intersections) 我們甚至還沒談到和泛型 (generic type) 有關的部分哩!而你都可在書中找到以上這些型別機制的詳盡介紹與範例。 [想了解更多內容?] 博客來79折優惠中(https://pse.is/3sv8j6) 與《完全自學!Go 語言 (Golang) 實戰聖經》合購享75折!