

為什麼要搞懂型別?
你有沒有過這種經驗——寫了一段 JavaScript,跑起來的時候莫名其妙出現 NaN 或 undefined is not a function?然後你花了半小時 debug,才發現是某個變數被傳成了錯誤的型別?
這就是為什麼理解型別這麼重要。TypeScript 的型別系統就像是一個「提前幫你抓蟲的朋友」,在你按下執行之前,就先告訴你哪裡可能出錯。搞懂基本型別,是用好 TypeScript 的第一步。
什麼是原始型別(Primitives)?
在 TypeScript 中,有三個最基本的原始型別:
| 型別 | 說明 | 範例 |
|---|---|---|
string | 字串 | "hello", 'world' |
number | 數字(整數或浮點數) | 42, 3.14 |
boolean | 布林值 | true, false |
型別註解語法
// 明確宣告型別
let name: string = "John";
let age: number = 25;
let isActive: boolean = true;
// TypeScript 也支援型別推論
let city = "Taipei"; // 自動推論為 string其他你一定會用到的型別
除了三大基本型別之外,還有幾個在實務開發中超常見的型別:
// null 和 undefined:表示「沒有值」
let nothing: null = null;
let notAssigned: undefined = undefined;
// void:通常用在不回傳值的 function
function logMessage(msg: string): void {
console.log(msg);
}
// any:放棄型別檢查(能不用就不用!)
let anything: any = "hello";
anything = 42; // 不會報錯,但你也失去了保護
// unknown:比 any 安全的「我不確定是什麼型別」
let mystery: unknown = "could be anything";
// mystery.toUpperCase(); // 報錯!必須先確認型別
if (typeof mystery === "string") {
mystery.toUpperCase(); // 這樣才行
}
// never:表示永遠不會發生的情況
function throwError(msg: string): never {
throw new Error(msg);
}陣列與聯合型別
// 陣列有兩種寫法,效果一樣
let fruits: string[] = ["apple", "banana"];
let numbers: Array<number> = [1, 2, 3];
// 聯合型別:一個變數可以是多種型別
let id: string | number;
id = "abc"; // OK
id = 123; // 也 OK
// Type Alias:幫型別取一個好記的名字
type UserID = string | number;
let myId: UserID = "user-001";什麼時候用哪個型別?
| 情境 | 建議使用 | 原因 |
|---|---|---|
| 明確知道型別 | string, number, boolean | 最安全、最清楚 |
| 可能是多種型別 | 聯合型別 A | B | 保有彈性又有檢查 |
| 不確定型別 | unknown | 強制你在使用前做型別檢查 |
| 從 JS 遷移、暫時跳過 | any | 最後手段,盡快替換掉 |
| function 不回傳值 | void | 明確表達意圖 |
| 不可能執行到的程式碼 | never | 例如永遠 throw error |
常見踩坑
- 別用大寫的
String、Number、Boolean——這些是包裝物件(wrapper objects),不是原始型別。TypeScript 會在編譯時期檢查型別,用小寫的就對了。 - 少用
any——用了any等於告訴 TypeScript「別管我」,你就回到了寫 JavaScript 的狀態,失去所有型別保護。如果真的不確定型別,用unknown比較安全,因為它會強迫你在使用前做型別檢查。 null和undefined的差別——null是你主動設定的「沒有值」,undefined是系統預設的「還沒給值」。在 TypeScript 嚴格模式下,這兩個不能隨便互換。