cover

概念圖

為什麼要搞懂型別?

你有沒有過這種經驗——寫了一段 JavaScript,跑起來的時候莫名其妙出現 NaNundefined 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

常見踩坑

  • 別用大寫的 StringNumberBoolean——這些是包裝物件(wrapper objects),不是原始型別。TypeScript 會在編譯時期檢查型別,用小寫的就對了。
  • 少用 any——用了 any 等於告訴 TypeScript「別管我」,你就回到了寫 JavaScript 的狀態,失去所有型別保護。如果真的不確定型別,用 unknown 比較安全,因為它會強迫你在使用前做型別檢查。
  • nullundefined 的差別——null 是你主動設定的「沒有值」,undefined 是系統預設的「還沒給值」。在 TypeScript 嚴格模式下,這兩個不能隨便互換。

延伸閱讀