前言 什麼是 Template Literals 類型? 在 TypeScript 中,Template Literals 類型是 ES6 引入的一個強大的功能。 Template literals ,主要用來加強字串的操作,它提供了更靈活和易讀的字串插值方式, 這不僅提高了代碼的可讀性,結合上 TypeScript 還可以增加了類型安全性 。 本篇提供大量範例與適用場景以供測試,有任何問題歡迎提出。
基礎應用(JS/TS 都適用) 字串插值 (String Interpolation) 傳統的字串拼接需要用 + 號,使用 Template Literals 可以讓拼接更簡單。
1 2 3 4 5 6 7 8 9 10 const name = "Lin" ;const age = 30 ;const message = "My name is " + name + " and I am " + age + " years old." ;const message2 = `My name is ${name} and I am ${age} years old.` ;console .log (message2);
多行字串 (Multi-line Strings) Template literals 支援多行字串,可以避免使用 \n
或其他換行符號。
1 2 3 4 5 6 7 8 const poem = ` Roses are red, Violets are blue, Sugar is sweet, And so are you. ` ;console .log (poem);
內嵌表達式 (Embedded Expressions) 可以在字串中插入任意的 JavaScript 表達式,例如函數調用、運算等。
1 2 3 4 const a = 5 ;const b = 10 ;console .log (`The sum of ${a} and ${b} is ${a + b} ` );
條件判斷 (Conditional Statements) 結合三元運算符或簡單的 if 判斷,可以在字串中靈活地處理條件。
1 2 3 4 const loggedIn = true ;const message = `You are ${loggedIn ? "logged in" : "not logged in" } .` ;console .log (message);
標記模板字串 (Tagged Templates) 標記模板允許你在插值之前處理字串,可以用於處理國際化、多語系或安全操作(如避免 XSS 攻擊)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 function sanitizeHTML (literals, ...values ) { let result = "" ; literals.forEach ((literal, i ) => { const value = values[i] ? String (values[i]).replace (/</g , "<" ).replace (/>/g , ">" ) : '' ; result += literal + value; }); return result; } const userInput = "<script>alert('Hacked!')</script>" ;const safeOutput = sanitizeHTML`<div>${userInput} </div>` ;console .log (safeOutput);
動態生成 HTML 或模版字串 當需要動態生成 HTML 或動態內容時,使用 Template Literals 可以讓結構更清晰。
1 2 3 4 5 6 7 8 9 const list = ["Apple" , "Banana" , "Cherry" ];const html = ` <ul> ${list.map(item => `<li>${item} </li>` ).join('' )} </ul> ` ;console .log (html);
進階應用 with Type 動態生成 URL 路徑 在構建 API 或動態路徑時,Template Literals 結合 TypeScript 類型檢查可以確保參數類型正確,避免拼接錯誤。
1 2 3 4 5 6 7 8 9 10 11 type Endpoint = "/users" | "/posts" | "/comments" ;function createURL (endpoint: Endpoint, id: number ): string { return `https://api.example.com${endpoint} /${id} ` ; } const url = createURL ("/users" , 123 );console .log (url); createURL ("/invalid" , 123 );
可以作開發中的路由檢查。
1 2 3 4 5 6 7 8 9 10 11 12 type HTTPMethod = "GET" | "POST" | "PUT" | "DELETE" ;type Route = `/api/${string } ` ;function request (method: HTTPMethod, route: Route ): void { console .log (`Sending ${method} request to ${route} ` ); } request ("GET" , "/api/users" ); request ("POST" , "/api/posts" ); request ("GET" , "/invalidRoute" );
相同的概念也可以來動態生成 SQL 查詢語句,同時確保參數的安全性與類型正確性。
1 2 3 4 5 6 7 8 9 10 11 type TableName = "users" | "posts" | "comments" ;function selectFromTable (table: TableName, id: number ): string { return `SELECT * FROM ${table} WHERE id = ${id} ` ; } const query = selectFromTable ("users" , 1 );console .log (query); selectFromTable ("invalidTable" , 1 );
字串聯合類型構造器 一個常見的模式是將Template Literals 類型與聯合類型結合,這樣可以生成所有可能的組合。 例如,假設我們有一組顏色和相應的色調:
1 2 type ColorShade = 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 ;type Color = "red" | "blue" | "green" ;
我們可以創建一個顏色調色板,代表所有可能的顏色和色調的組合:
1 2 3 type ColorPalette = `${Color} -${ColorShade} ` ;let color : ColorPalette = "red-500" ; let badColor : ColorPalette = "red" ;
這樣,我們就得到了 27 種可能的組合(3 種顏色乘以 9 種色調)。 又或者,在樣式生成工具或 CSS-in-JS 的場景中,Template Literals 可以結合類型系統來強化樣式生成工具的正確性。
1 2 3 4 5 6 7 8 9 10 11 12 type CSSUnit = "px" | "em" | "rem" ;type CSSProperty = "margin" | "padding" | "font-size" ;function applyStyle (property: CSSProperty, value: number , unit: CSSUnit ): string { return `${property} : ${value} ${unit} ;` ; } console .log (applyStyle ("margin" , 10 , "px" )); console .log (applyStyle ("font-size" , 1.5 , "em" )); applyStyle ("background" , 10 , "px" );
另一個例子 在構建大型系統時,常常需要動態生成變量名稱或類型, 這時可以使用 Template Literal Types 來幫助構造更具彈性的類型系統。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 type Eventa = "click" | "hover" | "focus" ;type ElementID = "button" | "input" | "link" ;type EventHandlerName <E extends Eventa , T extends ElementID > = `${T} On${Capitalize<E>} Handler` ;const buttonOnClickHandler : EventHandlerName <"click" , "button" > = "buttonOnClickHandler" ;const buttonOnHoverHandler : EventHandlerName <"hover" , "button" > = "buttonOnHoverHandler" ;const buttonOnFocusHandler : EventHandlerName <"focus" , "button" > = "buttonOnFocusHandler" ;const inputOnClickHandler : EventHandlerName <"click" , "input" > = "inputOnClickHandler" ;const inputOnHoverHandler : EventHandlerName <"hover" , "input" > = "inputOnHoverHandler" ;const inputOnFocusHandler : EventHandlerName <"focus" , "input" > = "inputOnFocusHandler" ;const linkOnClickHandler : EventHandlerName <"click" , "link" > = "linkOnClickHandler" ;const linkOnHoverHandler : EventHandlerName <"hover" , "link" > = "linkOnHoverHandler" ;const linkOnFocusHandler : EventHandlerName <"focus" , "link" > = "linkOnFocusHandler" ;const invalidHandler : EventHandlerName <"click" , "button" > = "buttonOnHoverHandler" ;
參考網路上的例子 Template Literals 類型允許我們在 TypeScript 中插入其他類型到字符串類型中。 例如,假設我們想要定義一個表示 PNG 文件的類型:
1 type Excel = `${string } .xlsx` ;
這樣,當我們為變量指定 Excel 類型時,它必須以 .xlsx 結尾:
1 2 let new_excel : Excel = "my-image.xlsx" ; let old_excel : Excel = "my-image.xls" ;
當字符串不符合定義時,TypeScript 會顯示錯誤提示,這有助於減少潛在的錯誤。 我們可以確保字符串符合特定的前綴或中間包含特定子字符串。 例如,若要確保路由以 /
開頭,我們可以這樣定義:
1 2 3 type Route = `/${string } ` ;const myRoute : Route = "/home" ; const badRoute : Route = "home" ;
同樣的,如果我們需要確保字符串包含 ?,以便視為查詢字符串,我們可以這樣定義:
1 2 3 type QueryString = `${string } ?${string } ` ;const myQueryString : QueryString = "search?query=hello" ; const badQueryString : QueryString = "search" ;
此外,TypeScript 還提供了一些內建的實用類型來轉換字符串類型,例如 Uppercase 和 Lowercase,可以將字符串轉換為大寫或小寫:
1 2 type UppercaseHello = Uppercase <"hello" >; type LowercaseHELLO = Lowercase <"HELLO" >;
還有 Capitalize 和 Uncapitalize 這兩個實用類型,可以用來改變字符串的首字母大小寫:
1 2 type CapitalizeMatt = Capitalize <"matt" >; type UncapitalizePHD = Uncapitalize <"PHD" >;
這些功能展示了 TypeScript 類型系統的靈活性。
結語 Template Literals 類型是一個非常有用的特性,能夠幫助開發者在 TypeScript 中更精確地控制字符串類型。 從定義特定格式的文件名到生成複雜的組合類型,它為代碼提供了更高的可讀性和安全性。 如果你在開發過程中需要處理字符串模式,Template Literals 類型無疑是值得考慮的工具。
參考
(fin)