TypeScript 基本型別(Primitive Types)
string、number、boolean
簡介
在任何程式語言中,**型別(type)**都是最基礎、也是最重要的概念之一。它不僅決定了變數能存什麼樣的資料,還直接影響程式的可讀性、維護成本與執行效能。TypeScript 作為 JavaScript 的超集合,透過靜態型別檢查,讓開發者在編譯階段就能捕捉到許多潛在的錯誤,提升開發效率與程式品質。
本單元聚焦於 三個最常使用的原始型別:string、number、boolean。它們分別代表文字、數值與布林值,幾乎所有的業務邏輯都會與這三種型別打交道。了解它們在 TypeScript 中的行為、限制與最佳實踐,能讓你寫出更安全、更具表達力的程式碼。
核心概念
1. string – 文字資料
在 TypeScript 中,string 用來表示一串 Unicode 文字。與 JavaScript 相同,字串可以使用單引號 ('...')、雙引號 ("...") 或是 ES6 引入的 模板字面值(template literals)(`...`)來宣告。
1.1 基本宣告與型別推斷
let greeting: string = 'Hello, TypeScript!'; // 明確指定型別
let name = "Alice"; // 型別推斷為 string
1.2 模板字面值與表達式插值
模板字面值允許在字串中直接嵌入變數或運算式,寫起來更直觀。
const age = 28;
const intro = `我叫 ${name},今年 ${age} 歲。`; // ${} 內可寫任意表達式
1.3 常用字串方法
TypeScript 繼承了 JavaScript 的所有字串方法,且在編譯階段會提供完整的型別資訊。
// 判斷字串是否以特定前綴開頭
if (greeting.startsWith('Hello')) {
console.log('問候語以 Hello 開頭');
}
// 取出子字串
const sub = greeting.slice(0, 5); // "Hello"
1.4 字串聯集型別(String Literal Types)
TypeScript 允許把字串寫成 字面值型別,用於限制變數只能接受特定的文字。
type Direction = 'up' | 'down' | 'left' | 'right';
let move: Direction = 'up'; // 正確
// move = 'forward'; // 編譯錯誤:型別不符合
2. number – 數值資料
number 在 TypeScript 中代表 IEEE 754 雙精度浮點數,同時支援整數、浮點數、十六進位、二進位與八進位寫法。沒有 int、float 等子型別,所有數字皆屬於同一型別。
2.1 基本宣告
let count: number = 42; // 整數
let price = 99.95; // 浮點數(型別推斷)
let hex = 0xFF; // 十六進位
let bin = 0b1010; // 二進位
let oct = 0o755; // 八進位
2.2 數字運算
const radius = 5;
const area = Math.PI * radius ** 2; // ** 為次方運算子
console.log(`圓面積為 ${area.toFixed(2)}`);
2.3 NaN、Infinity 與型別安全
NaN(Not a Number)與 Infinity 也是 number 型別的合法值,但在實務開發中往往需要特別處理。
function safeDivide(a: number, b: number): number {
if (b === 0) {
return Infinity; // 或拋出例外
}
return a / b;
}
const result = safeDivide(10, 0);
if (!Number.isFinite(result)) {
console.warn('除以零產生無限大');
}
2.4 數字字面值型別(Numeric Literal Types)
類似字串字面值型別,數字也可以限定為特定值的聯集。
type Dice = 1 | 2 | 3 | 4 | 5 | 6;
function roll(): Dice {
return (Math.floor(Math.random() * 6) + 1) as Dice;
}
3. boolean – 布林值
boolean 只有兩個可能的值:true 或 false。在 TypeScript 中,布林值常用於條件判斷、流程控制與型別守衛(type guard)。
3.1 基本宣告
let isActive: boolean = true;
let isDone = false; // 型別推斷為 boolean
3.2 與條件式結合
if (isActive && !isDone) {
console.log('任務尚未完成且仍在執行');
}
3.3 真值(truthy)與偽值(falsy)的差異
雖然 JavaScript 允許使用任何「真值」或「偽值」在條件式中,TypeScript 建議仍以 boolean 為主,以避免隱性類型轉換帶來的錯誤。
let count = 0;
if (count) { // 這裡會被視為偽值,但型別是 number
// ...不建議這樣寫
}
// 正確寫法
let hasItems: boolean = count > 0;
if (hasItems) {
// ...
}
3.4 布林字面值型別
type YesNo = true | false;
let answer: YesNo = true; // 明確指定
程式碼範例(實用範例)
以下示範 5 個在日常開發中常見且實用的範例,涵蓋 string、number、boolean 的互動與型別安全。
範例 1:表單驗證(字串與布林)
type ValidationResult = {
valid: boolean;
message: string;
};
function validateEmail(email: string): ValidationResult {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
const isValid = emailRegex.test(email);
return {
valid: isValid,
message: isValid ? 'Email 格式正確' : '請輸入有效的 Email',
};
}
// 使用
const userEmail = 'alice@example.com';
const result = validateEmail(userEmail);
if (!result.valid) {
console.error(result.message);
}
重點:
valid為boolean,message為string,型別明確讓錯誤訊息更易追蹤。
範例 2:計算折扣(數字與字串)
function calculateDiscount(price: number, rate: number): string {
const discounted = price * (1 - rate);
// 使用 toFixed 固定小數點兩位,並加上貨幣符號
return `$${discounted.toFixed(2)}`;
}
// 呼叫
console.log(calculateDiscount(1200, 0.15)); // $1020.00
說明:
price、rate必須是number,返回值是格式化後的string,避免在 UI 層再次轉型。
範例 3:旗標(Flag)控制流程
type FeatureToggle = {
darkMode: boolean;
betaAccess: boolean;
};
function renderUI(toggles: FeatureToggle) {
const theme = toggles.darkMode ? 'dark' : 'light';
console.log(`使用 ${theme} 主題`);
if (toggles.betaAccess) {
console.log('顯示 Beta 功能區塊');
}
}
// 範例
renderUI({ darkMode: true, betaAccess: false });
技巧:把多個布林值集中在一個物件中,讓程式碼更具可讀性與擴充性。
範例 4:枚舉(Enum)結合字串字面值
enum LogLevel {
INFO = 'info',
WARN = 'warn',
ERROR = 'error',
}
function log(message: string, level: LogLevel = LogLevel.INFO): void {
console[level](`[${level.toUpperCase()}] ${message}`);
}
// 使用
log('系統啟動完成'); // 預設 INFO
log('磁碟空間不足', LogLevel.WARN);
log('未捕獲的例外', LogLevel.ERROR);
說明:
LogLevel以字串值實作,配合enum提供自動補全與型別安全。
範例 5:型別守衛(Type Guard)範例
function formatValue(value: string | number | boolean): string {
if (typeof value === 'string') {
return `"${value}"`; // 文字加上引號
}
if (typeof value === 'number') {
return value.toFixed(2); // 數字保留兩位小數
}
// 此時 value 必為 boolean
return value ? '是' : '否';
}
// 測試
console.log(formatValue('TS')); // "TS"
console.log(formatValue(3.1415)); // 3.14
console.log(formatValue(false)); // 否
重點:利用
typeof進行型別守衛,讓每個分支的value變成確定的型別,避免不必要的型別斷言。
常見陷阱與最佳實踐
| 陷阱 | 說明 | 建議的最佳實踐 |
|---|---|---|
| 隱式 any | 未宣告型別或未啟用 noImplicitAny,導致變數被推斷為 any,失去型別保護。 |
在 tsconfig.json 中開啟 noImplicitAny,並盡量使用顯式型別或型別推斷。 |
| 字串與數字的隱式轉換 | JavaScript 會自動把字串與數字互相轉換,可能產生意外結果。 | 在 TypeScript 中避免使用 ==,改用 ===;必要時手動轉型(Number(str)、String(num))。 |
NaN 與 Infinity 的誤用 |
許多運算會產生 NaN,但 NaN !== NaN,容易導致判斷失效。 |
使用 Number.isNaN(value)、Number.isFinite(value) 進行檢查。 |
| 布林值的偽值陷阱 | 把 0、''、null、undefined 當作 false 使用,會讓程式行為不一致。 |
明確使用 boolean 型別,或在條件式前先做類型檢查 (value === true)。 |
| 字面值型別過度使用 | 為每個字串/數字建立字面值型別,會讓型別宣告過於繁雜。 | 僅在需要限制取值範圍(如 API 參數、狀態機)時使用;否則使用普通 string/number。 |
其他最佳實踐
- 使用
const取代let:對於不會重新指派的變數,使用const能讓編譯器更好地推斷出 字面值型別(例如'up'而非string)。 - 啟用嚴格模式:
"strict": true能自動開啟多項檢查,包括strictNullChecks,避免null/undefined帶來的意外。 - 盡量避免
any:若真的需要暫時使用,可改用unknown,在使用前必須先做型別檢查,保持安全性。 - 利用
as const:對於陣列或物件的常量,使用as const讓其屬性變成 只讀字面值型別,減少誤寫。 - 保持一致的字串引號風格:團隊可統一使用單引號或雙引號,或是根據 ESLint 規則自動格式化。
實際應用場景
| 場景 | 為何需要嚴格的原始型別 | 範例 |
|---|---|---|
| API 請求/回應 | 後端資料結構通常固定,錯誤的型別會導致 UI 無法正確呈現。 | 定義 interface User { id: number; name: string; isActive: boolean; },在 fetch 後使用 as User 前先做型別守衛。 |
| 表單驗證 | 使用者輸入的文字、數字、勾選框分別對應 string、number、boolean,若混用會產生驗證錯誤。 |
參考「範例 1」的 validateEmail,把每個欄位的型別寫清楚。 |
| 狀態機(State Machine) | 狀態往往是有限集合(如 `'idle' | 'loading' |
| 計算與統計 | 金額、比率等必須是 number,避免文字相加造成錯誤。 |
參考「範例 2」的價格折扣計算。 |
| 功能開關(Feature Flag) | 多個布林旗標控制功能顯示與行為,若誤把字串 'true' 當布林,會導致邏輯錯亂。 |
參考「範例 3」的 FeatureToggle 物件。 |
總結
string、number、boolean是 TypeScript 中最基礎、最常見的三種原始型別,掌握它們的宣告、操作方式與型別安全是寫好任何程式的根基。- 透過 字面值型別、模板字面值、型別守衛 等語法,TypeScript 能在編譯階段即捕捉錯誤,提升開發效率與程式可靠度。
- 在實務開發中,避免隱式轉型、適時使用嚴格模式、明確標註型別,是防止常見陷阱的關鍵。
- 只要養成 以型別為中心的思考方式,在 API、表單、狀態管理與業務邏輯等場景下,都能寫出乾淨、易維護的 TypeScript 程式碼。
祝你在 TypeScript 的旅程中,從基礎型別踏出堅實的第一步,開發出更安全、更可靠的前端與全端應用! 🚀