在 JavaScript 裡,我們可以用模板字串:
ts
CopyEdit
const name = "Alice";
const message = `Hello, ${name}!`;
TypeScript 從 4.1 開始,讓型別系統也能玩這種「字串拼接」,
而且還能搭配 Union、條件型別 來自動生成型別。
這意味著:
"onClick"
、"onChange"
)ts
CopyEdit
type EventName<T extends string> = `on${Capitalize<T>}`;
type ClickEvent = EventName<"click">; // "onClick"
這裡:
...
是模板字面型別語法${}
裡面可以放 型別參數 或其他型別運算Capitalize<T>
是 TS 內建的字串轉換工具Uppercase<S>
:轉成全大寫Lowercase<S>
:轉成全小寫Capitalize<S>
:首字母大寫Uncapitalize<S>
:首字母小寫範例:
ts
CopyEdit
type A = Uppercase<"hello">; // "HELLO"
type B = Lowercase<"Hello">; // "hello"
type C = Capitalize<"hello">; // "Hello"
type D = Uncapitalize<"Hello">; // "hello"
ts
CopyEdit
type Events = "click" | "change";
type EventHandlers = `on${Capitalize<Events>}`;
// "onClick" | "onChange"
這招在定義事件名稱、API 路徑、CSS class 名稱等非常好用。
ts
CopyEdit
type Endpoints = "users" | "posts" | "comments";
type ApiPaths = `/api/${Endpoints}`;
// "/api/users" | "/api/posts" | "/api/comments"
這樣改 API 路徑名稱只要改一個地方,型別會自動更新。
ts
CopyEdit
type BaseEvents = "click" | "hover" | "focus";
type DOMEvents = `on${Capitalize<BaseEvents>}`;
function addEventListener<E extends DOMEvents>(event: E) {
console.log(`Listening to ${event}`);
}
addEventListener("onClick"); // OK
addEventListener("onHover"); // OK
addEventListener("onclick"); // ❌ 型別錯誤
ts
CopyEdit
type States = "loading" | "success" | "error";
type StateLabels = `${Uppercase<States>}_STATE`;
// "LOADING_STATE" | "SUCCESS_STATE" | "ERROR_STATE"
ts
CopyEdit
type SnakeToCamel<S extends string> =
S extends `${infer First}_${infer Rest}`
? `${First}${Capitalize<SnakeToCamel<Rest>>}`
: S;
type A = SnakeToCamel<"user_name">; // "userName"
這個技巧可以搭配 Day 25 的映射型別,把 API 回應自動轉成駝峰命名。
錯誤 1:把值當型別
ts
CopyEdit
const path = "/api/users";
type Wrong = `/api/${path}`; // ❌ path 是值,不是型別
→ 必須改成字面型別:
ts
CopyEdit
type Path = "/api/users";
type Correct = `/api/${Path}`;
錯誤 2:忘記 extends string
限制
ts
CopyEdit
type Test<T> = `prefix-${T}`; // ❌ 可能不是 string
→ 應該:
ts
CopyEdit
type Test<T extends string> = `prefix-${T}`;