iT邦幫忙

2022 iThome 鐵人賽

DAY 29
0
Modern Web

Hello TypeScript 菜鳥系列 第 29

Day 28. TypeScript Type Manipulation:Template Literal Types

  • 分享至 

  • xImage
  •  

TypeScript的template literal types類似於JavaSctipt的樣板字串(template literal),熟悉template literal的人應該就會使用template literal types的最基本語法:

type HelloWorld = `Hello ${World}`;	// type HelloWorld = "Hello World"

雖然template literal types語法看似簡單,但別忘了TypeScript內建非常豐富的型別,還有很多取得或創造型別的方法,所以template literal types強大的地方在於如何和其他型別、關鍵字和運算子一起運用。

譬如先以最常見的union型別來看template literal types的應用:

type Event = "up" | "press" | "down";
type KeyEvent = `key${Event}`;	// type KeyEvent = "keyup" | "keypress" | "keydown"

若template literal types裡有union型別,則字串就會與union型別裡的每個型別作cross-join(或者說Cartesian product)。

同樣地,如果是兩個union型別一起放在template literal types,則兩個union型別裡各自的型別也會兩兩作cross join,如範例

type Letter = "A" | "B" | "C" | "D";
type Level = "+" | "" | "-";

type Scores = `${Letter}${Level}`;
	// type Scores = "A" | "B" | "C" | "D" | "A+" | "B+" | "C+" | "D+" | "A-" | "B-" | "C-" | "D-"

相較於自己一個個輸入這些長相類似的型別,利用template literal types和union型別,不僅能很輕鬆地產生大量的literal types,也能避免手動輸入容易產生錯字的問題。


TypeScript利用template literal types的性質提供幾個內建可操作string的型別,分別是:

  • Uppercase<StringType>:型別名稱每個字母都轉換成大寫字母
  • Lowercase<StringType>:型別名稱每個字母都轉換成小寫字母
  • Capitalize<StringType>:型別名稱第一個字母轉換成大寫字母
  • Uncapitalize<StringType>:型別名稱除第一個字母以外的字母都轉換成大寫字母

可以運用以上的型別,再加上template literal types可以讓union型別cross join的性質,就能輕易地創造出這些像JavaScript裡使用的camelCase版CSS屬性型別,舉例如下:

type BgAttr = "color" | "image" | "repeat" | "attachment" | "position";
type Background = `background${Capitalize<BgAttr>}`;

	// type Background = "backgroundColor" | "backgroundImage" | "backgroundRepeat" | "backgroundAttachment" | "backgroundPosition"

另外,官方文件有提供一個一丁點複雜的範例,範例很巧妙地運用型別推導(type inference)、indexed accessed types和generic types等性質。

以下也來試著用這些性質搭配template literal types來創造一個物件,假設想要已經存在的物件創造一個有相同屬性但屬性名稱是小寫開頭的物件型別...

type CamalCase = {
	Id: any;
	Type: string;
	OnChange: () => void;
	OnClick: (p: Event) => void;
}

type camelCase = {
	[Key in keyof CamalCase as `${Uncapitalize<Key>}`]: CamalCase[Key]
}

	/*
		type camelCase = {
			id: any;
			type: string;
			onChange: () => void;
			onClick: (p: Event) => void;
		}
	*/

範例運用了 in 關鍵字和 keyof 型別運算子去取得CamalCase物件型別的屬性,並且透過template literal types改為小寫開頭的屬性名稱。

從範例可以發現多運用TypeScript的型別方法,再使用template literal types就能更靈活地產生需要的型別,而且也確保產生預期中的型別(除非有語法或邏輯上的錯誤XD)。

今天篇幅比較少一些,主要是因為這篇的目的是認識template literal typs語法,而且考慮到這是菜鳥系列,所以只使用幾個前幾天有學過的關鍵字、運算子來看template literal types的一些入門應用。

至於比較進階的template literal typs使用方法,也就是融合很多關鍵字或運算子的應用XD,可以參考官方文件這篇或是其他優秀的文章


參考資料
Template Literal Types
Mastering TypeScript Template Literal Types
TypeScript: Template Literal Types


上一篇
Day 27. TypeScript Type Manipulation:Conditional Types
下一篇
Day 29. TypeScript Type Manipulation: Mapped Types
系列文
Hello TypeScript 菜鳥31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言