了解TypeScript資料類型中的範本字面量
TypeScript團隊發布了TypeScript 4.1,其中包括強大的模板字面量類型、映射類型的鍵重映射以及遞歸條件類型。以下這篇文章就來帶大家了解一下TypeScript中的模板字面量類型,希望對大家有幫助!
範本字面類型(Template Literal Types)
範本字面類型以字串字面量類型為基礎,可以透過聯合類型擴展成多個字串。
它們跟 JavaScript 的模板字串是相同的語法,但是只能用在型別操作中。當使用模板字面量類型時,它會替換模板中的變量,返回一個新的字串字面量:
type World = "world"; type Greeting = `hello ${World}`; // type Greeting = "hello world"
當模板中的變量是一個聯合類型時,每一個可能的字串字面量都會被表示:
type EmailLocaleIDs = "welcome_email" | "email_heading"; type FooterLocaleIDs = "footer_title" | "footer_sendoff"; type AllLocaleIDs = `${EmailLocaleIDs | FooterLocaleIDs}_id`; // type AllLocaleIDs = "welcome_email_id" | "email_heading_id" | "footer_title_id" | "footer_sendoff_id"
如果模板字面量裡的多個變數都是聯合類型,結果會交叉相乘,例如下面的例子就有2 2 3 一共12 種結果:
type AllLocaleIDs = `${EmailLocaleIDs | FooterLocaleIDs}_id`; type Lang = "en" | "ja" | "pt"; type LocaleMessageIDs = `${Lang}_${AllLocaleIDs}`; // type LocaleMessageIDs = "en_welcome_email_id" | "en_email_heading_id" | "en_footer_title_id" | "en_footer_sendoff_id" | "ja_welcome_email_id" | "ja_email_heading_id" | "ja_footer_title_id" | "ja_footer_sendoff_id" | "pt_welcome_email_id" | "pt_email_heading_id" | "pt_footer_title_id" | "pt_footer_sendoff_id"
如果真的是非常長的字串聯合類型,推薦提前生成,這種還是適用於短一些的情況。
類型中的字串聯合類型(String Unions in Types)
模板字面量最有用的地方在於你可以基於一個類型內部的信息,定義一個新的字串,讓我們舉個例子:
有這樣一個函數makeWatchedObject
, 它會為傳入的物件增加了一個on
方法。在JavaScript 中,它的呼叫看起來是這樣:makeWatchedObject(baseObject)
,我們假設這個傳入物件為:
const passedObject = { firstName: "Saoirse", lastName: "Ronan", age: 26, };
這個on
方法會被添加到這個傳入物件上,該方法接受兩個參數,eventName
( string
類型) 和callBack
(function
類型):
// 伪代码 const result = makeWatchedObject(baseObject); result.on(eventName, callBack);
我們希望eventName
是這種形式:attributeInThePassedObject "Changed"
,舉個例子,passedObject
有一個屬性firstName
,對應產生的eventName
為firstNameChanged
,同理,lastName
對應的是lastNameChanged
,age
對應的是ageChanged
。
當這個 callBack
函數被呼叫的時候:
- 應該被傳入與
attributeInThePassedObject
相同類型的值。例如passedObject
中,firstName
的值的型別為string
, 對應firstNameChanged
事件的回呼函數,則接受傳入一個string
類型的值。age
的值的型別為number
,對應ageChanged
事件的回呼函數,則接受傳入一個number
類型的值。 - 傳回值類型為
void
類型。
on()
方法的簽章最一開始是這樣的:on(eventName: string, callBack: (newValue: any) => void)
。使用這樣的簽名,我們是不能實現上面所說的這些約束的,這個時候就可以使用模板字面量:
const person = makeWatchedObject({ firstName: "Saoirse", lastName: "Ronan", age: 26, }); // makeWatchedObject has added `on` to the anonymous Object person.on("firstNameChanged", (newValue) => { console.log(`firstName was changed to ${newValue}!`); });
注意這個例子裡,on
方法添加的事件名為"firstNameChanged"
,而不僅僅是"firstName"
,而回呼函數傳入的值newValue
,我們希望約束為string
類型。我們先實現第一點。
在這個例子裡,我們希望傳入的事件名稱的類型,是物件屬性名稱的聯合,只是每個聯合成員都還在最後拼接一個Changed
字符,在JavaScript中,我們可以做這樣一個計算:
Object.keys(passedObject).map(x => ${x}Changed)
模板字面量提供了一個相似的字串操作:
type PropEventSource<Type> = { on(eventName: `${string & keyof Type}Changed`, callback: (newValue: any) => void): void; }; /// Create a "watched object" with an 'on' method /// so that you can watch for changes to properties. declare function makeWatchedObject<Type>(obj: Type): Type & PropEventSource<Type>;
注意,我們在這裡例子中,模板字面量裡我們寫的是string & keyof Type
,我們可不可以只寫成keyof Type
呢?如果我們這樣寫,會報錯:
type PropEventSource<Type> = { on(eventName: `${keyof Type}Changed`, callback: (newValue: any) => void): void; }; // Type 'keyof Type' is not assignable to type 'string | number | bigint | boolean | null | undefined'. // Type 'string | number | symbol' is not assignable to type 'string | number | bigint | boolean | null | undefined'. // ...
從報錯訊息中,我們也可以看出報錯原因,在《TypeScript 系列之Keyof 運算子》裡,我們知道keyof
運算子會回傳string | number | symbol
類型,但是模板字面量的變數要求的型別卻是string | number | bigint | boolean | null | undefined
,比較一下,多了一個symbol 類型,所以其實我們也可以這樣寫:
type PropEventSource<Type> = { on(eventName: `${Exclude<keyof Type, symbol>}Changed`, callback: (newValue: any) => void): void; };
再或這樣寫:
type PropEventSource<Type> = { on(eventName: `${Extract<keyof Type, string>}Changed`, callback: (newValue: any) => void): void; };
使用這種方式,當我們使用錯誤的事件名稱時,TypeScript 會給出錯誤:
const person = makeWatchedObject({ firstName: "Saoirse", lastName: "Ronan", age: 26 }); person.on("firstNameChanged", () => {}); // Prevent easy human error (using the key instead of the event name) person.on("firstName", () => {}); // Argument of type '"firstName"' is not assignable to parameter of type '"firstNameChanged" | "lastNameChanged" | "ageChanged"'. // It's typo-resistant person.on("frstNameChanged", () => {}); // Argument of type '"frstNameChanged"' is not assignable to parameter of type '"firstNameChanged" | "lastNameChanged" | "ageChanged"'.
模板字面量的推論(Inference with Template Literals)
現在我們來實作第二點,回呼函數傳入的值的型別與對應的屬性值的類型相同。我們現在只是簡單的對 callBack
的參數使用 any
類型。實現這個約束的關鍵在於藉助泛型函數:
捕获泛型函数第一个参数的字面量,生成一个字面量类型
该字面量类型可以被对象属性构成的联合约束
对象属性的类型可以通过索引访问获取
应用此类型,确保回调函数的参数类型与对象属性的类型是同一个类型
type PropEventSource<Type> = { on<Key extends string & keyof Type> (eventName: `${Key}Changed`, callback: (newValue: Type[Key]) => void ): void; }; declare function makeWatchedObject<Type>(obj: Type): Type & PropEventSource<Type>; const person = makeWatchedObject({ firstName: "Saoirse", lastName: "Ronan", age: 26 }); person.on("firstNameChanged", newName => { // (parameter) newName: string console.log(`new name is ${newName.toUpperCase()}`); }); person.on("ageChanged", newAge => { // (parameter) newAge: number if (newAge < 0) { console.warn("warning! negative age"); } })
这里我们把 on
改成了一个泛型函数。
当一个用户调用的时候传入 "firstNameChanged"
,TypeScript 会尝试着推断 Key
正确的类型。它会匹配 key
和 "Changed"
前的字符串 ,然后推断出字符串 "firstName"
,然后再获取原始对象的 firstName
属性的类型,在这个例子中,就是 string
类型。
内置字符操作类型(Intrinsic String Manipulation Types)
TypeScript 的一些类型可以用于字符操作,这些类型处于性能的考虑被内置在编译器中,你不能在 .d.ts
文件里找到它们。
Uppercase
把每个字符转为大写形式:
type Greeting = "Hello, world" type ShoutyGreeting = Uppercase<Greeting> // type ShoutyGreeting = "HELLO, WORLD" type ASCIICacheKey<Str extends string> = `ID-${Uppercase<Str>}` type MainID = ASCIICacheKey<"my_app"> // type MainID = "ID-MY_APP"
Lowercase
把每个字符转为小写形式:
type Greeting = "Hello, world" type QuietGreeting = Lowercase<Greeting> // type QuietGreeting = "hello, world" type ASCIICacheKey<Str extends string> = `id-${Lowercase<Str>}` type MainID = ASCIICacheKey<"MY_APP"> // type MainID = "id-my_app"
Capitalize
把字符串的第一个字符转为大写形式:
type LowercaseGreeting = "hello, world"; type Greeting = Capitalize<LowercaseGreeting>; // type Greeting = "Hello, world"
Uncapitalize
把字符串的第一个字符转换为小写形式:
type UppercaseGreeting = "HELLO WORLD"; type UncomfortableGreeting = Uncapitalize<UppercaseGreeting>; // type UncomfortableGreeting = "hELLO WORLD"
字符操作类型的技术细节
从 TypeScript 4.1 起,这些内置函数会直接使用 JavaScript 字符串运行时函数,而不是本地化识别 (locale aware)。
function applyStringMapping(symbol: Symbol, str: string) { switch (intrinsicTypeKinds.get(symbol.escapedName as string)) { case IntrinsicTypeKind.Uppercase: return str.toUpperCase(); case IntrinsicTypeKind.Lowercase: return str.toLowerCase(); case IntrinsicTypeKind.Capitalize: return str.charAt(0).toUpperCase() + str.slice(1); case IntrinsicTypeKind.Uncapitalize: return str.charAt(0).toLowerCase() + str.slice(1); } return str; }
【相关推荐:javascript学习教程】
以上是了解TypeScript資料類型中的範本字面量的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

在MySQL資料庫中,性別欄位通常可以使用ENUM類型來儲存。 ENUM是一種枚舉類型,它允許我們在一組預先定義的值中選擇一個作為欄位的值。在表示性別這樣一個固定且有限的選項時,ENUM是一個很好的選擇。讓我們來看一個具體的程式碼範例:假設我們有一個名為"users"的表,其中包含了使用者的信息,包括性別。現在我們要為性別創建一個字段,我們可以這樣設計表結構:CRE

在MySQL中,最適合用於性別欄位的資料類型是ENUM枚舉類型。 ENUM枚舉類型是一種允許定義一組可能取值的資料類型,性別欄位適合使用ENUM類型是因為性別通常只有兩個取值,即男性和女性。接下來,我將透過具體的程式碼範例來展示如何在MySQL中建立一個性別欄位並使用ENUM枚舉類型儲存性別資訊。以下是操作步驟:首先,在MySQL中建立一個名為users的表格,包括

python憑藉其簡單易讀的語法,廣泛應用於廣泛的領域。掌握Python語法的基礎架構至關重要,既可以提高程式效率,又能深入理解程式碼的運作方式。為此,本文提供了一個全面的心智圖,詳細闡述了Python語法的各個面向。變數和資料類型變數是Python中用於儲存資料的容器。心智圖展示了常見的Python資料類型,包括整數、浮點數、字串、布林值和列表。每個資料類型都有其自身的特性和操作方法。運算符運算符用於對資料類型執行各種操作。心智圖涵蓋了Python中的不同運算子類型,例如算術運算子、比

MySQL中布林類型的使用方法詳解MySQL是一種常用的關聯式資料庫管理系統,在實際應用中經常需要使用布林類型來表示邏輯上的真假值。 MySQL中布林類型有兩種表示法:TINYINT(1)和BOOL。本文將詳細介紹MySQL中布林類型的使用方法,包括布林類型的定義、賦值、查詢和修改等操作,同時結合具體的程式碼範例進行說明。 1.布林類型的定義在MySQL中,可

在設計資料庫表時,選擇合適的資料類型對於效能最佳化和資料儲存效率非常重要。在MySQL資料庫中,儲存性別欄位的資料類型真是沒有所謂的最佳選擇,因為性別欄位一般只有兩個取值:男或女。但是為了效率和節省空間,我們可以選擇合適的資料類型來儲存性別欄位。在MySQL中,儲存性別欄位最常用的資料類型是枚舉類型。枚舉類型是一種能夠把欄位的值限定在一個有限的集合內的資料型別

C語言是一種廣泛使用的電腦程式語言,具有高效、靈活和強大的特點。要熟練使用C語言進行編程,首先需要了解其基本語法和資料類型。本文將介紹C語言的基本語法和資料類型,並舉例說明。一、基本語法1.1註解在C語言中,可以使用註解來對程式碼進行說明,以便於理解和維護。註解可以分為單行註解和多行註解。 //這是單行註解/*這是多行註解*/1.2關鍵字C語

標題:基本資料類型大揭密:了解主流程式語言中的分類正文:在各種程式語言中,資料類型是非常重要的概念,它定義了可以在程式中使用的不同類型的資料。對於程式設計師來說,了解主流程式語言中的基本資料類型是建立堅實程式基礎的第一步。目前,大多數主流程式語言都支援一些基本的資料類型,它們在語言之間可能有所差異,但主要概念是相似的。這些基本資料類型通常被分為幾個類別,包括整數

1.Python簡介python是一種簡單易學、功能強大的通用程式語言,由GuidovanRossum於1991年創建。 Python的設計理念是強調程式碼的可讀性,並為開發人員提供豐富的程式庫和工具,以幫助他們快速、有效率地建立各種應用程式。 2.Python基礎語法Python的基礎語法與其他程式語言類似,包括變數、資料型別、運算子、控制流程語句等。變數用於儲存數據,資料類型定義了變數可以儲存的資料類型,運算子用於對資料進行各種操作,控制流程語句用於控製程式的執行流程。 3.Python資料類型Python中
