這是我們今天要聊的內容,老樣的,如果你已經可以輕鬆看懂,歡迎直接左轉去看我同事 Kyle 精彩的文章 — 「今晚,我想來點 Web 前端效能優化大補帖!」。
大部分 JavaScript 的開發者都知道有 Template Literals / Template Strings(樣本字面值)可以使用,講中文可能大家反而不知道是什麼,但重點就是使用反引號(backtick)`
這個關鍵字,並可以在 ${}
裡面帶入變數,像是這樣:
const occupation = 'Web Developer';
const content = `Hello, I am a ${occupation}.`; // 'Hello, I am a Web Developer.'
而這個用法同樣可以在 TypeScript 中定義型別時使用,稱作 Template Literal Types。就讓我們直接把上面 JavaScript 的範例改成型別看看:
type Occupation = 'Web Developer';
type Content = `Hello, I am a ${Occupation}.`; // "Hello, I am a Web Developer."
用起來就和 JavaScript 的 Template Literals 一樣,就是這麼簡單!
這裡
Occupation
或Content
這種直接用字串來定義型別的方式稱作 String Literal Types。
在 TypeScript 中,Template Literal Types 除了可以像 JavaScript 直接帶入變數外,還可以帶入聯集型別(union types),而這是個非常實用的功能。
舉例來說:
type HandledEvent = 'change' | 'click' | 'keydown';
type EventHandler = `on${HandledEvent}`; // "onchange" | "onclick" | "onkeydown"
在上面的例子中可以看到 HandledEvent
是一個 Union Type,當我們把 Union Type 放到 Template Literal Types 中時,TypeScript 會根據所傳入的聯集,自動組成新的聯集(即,"onchange" | "onclick" | "onkeydown"
),這個感覺有點類似前幾天提到的分配律。
現在讓我們回到今天一開始的例子:
type X = 'left' | 'right';
type Y = 'top' | 'bottom';
type Position = `${X}-${Y}`;
現在讀者應該可以理解 Position
的型別最終會得到什麼。因為 X
傳入的是聯集 "left" | "right"
,而 Y
也同樣是聯集 "top" | "bottom"
,因此最終 Position
這個型別就會是 "left-top" | "left-bottom" | "right-top" | "right-bottom"
。
透過 Template Literal Types 這樣的特性可以幫助開發者方便快速的產生所需要的型別。
在 TypeScript 中很常會只用到 enum,像是:
enum MANUFACTURE {
APPLE = 'apple',
SAMSUNG = 'samsung',
GOOGLE = 'google',
SONY = 'sony',
}
有時我們想要根據 enum 的 values 來產生出新的型別,如果透過手動定義的話很麻煩,會是這樣:
type Manufacture = 'apple' | 'samsung' | 'google' | 'sony';
而且未來如果 MANUFACTURE
有添加新的內容時,還要記得回過頭來修改 Manufacture
這個型別,非常不方便。
當有這種需求時,實際上可以使用 Template Literal Types 來解決:
type Manufacture = `${MANUFACTURE}`; // "apple" | "samsung" | "google" | "sony"
就是這麼簡單,一行搞定!
https://tsplay.dev/WzoKew @ TypeScript Playground