成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

用了模板字面量類型,同事直呼太強了!

開發 前端
假設我們想要定義一種類型來描述 CSS padding 規則,如果你了解 TypeScript 類型別名和聯合類型的話,能很容易定義出 CssPadding 類型。

你了解過模板字面量類型么?你想知道如何利用模板字面量類型,來減少 TypeScript 項目中的重復代碼么?如果想的話,閱讀完本文內容之后,也許你就懂了。

假設我們想要定義一種類型來描述 CSS padding 規則,如果你了解 TypeScript 類型別名和聯合類型的話,能很容易定義出 CssPadding 類型。

type CssPadding =
| "padding-left"
| "padding-right"
| "padding-top"
| "padding-bottom";

圖片

但如果我們想要繼續定義一種新的類型來描述 CSS margin 規則,你是不是立馬想到與定義 CssPadding 類型一樣的方式。

type MarginPadding =
| "margin-left"
| "margin-right"
| "margin-top"
| "margin-bottom";

圖片

對于以上定義的兩種類型來說,雖然它們都能滿足我們的需求。但在定義這兩種類型的過程中,仍然存在一些重復的代碼。

那么如何解決這個問題呢?這時我們可以使用 TypeScript 4.1 版本引入了新的模板字面量類型,具體的使用方式如下:

type Direction = "left" | "right" | "top" | "bottom";

type CssPadding = `padding-${Direction}`;
type MarginPadding = `margin-${Direction}`;

看完以上代碼,是不是覺得簡潔很多。與 JavaScript 中的模板字符串類似,模板字面量類型被括在反引號中,同時可以包含 ${T}? 形式的占位符,其中類型變量 T 的類型可以是 string、number、boolean? 或 bigint 類型。

圖片

模板字面量類型不僅為我們提供了連接字符串字面量的能力,而且還可以把非字符串基本類型的字面量轉換為對應的字符串字面量類型。下面我們來舉一些具體的例子:

type EventName<T extends string> = `${T}Changed`;
type Concat<S1 extends string, S2 extends string> = `${S1}-${S2}`;
type ToString<T extends string | number | boolean | bigint> = `${T}`;

type T0 = EventName<"foo">; // 'fooChanged'
type T1 = Concat<"Hello", "World">; // 'Hello-World'
type T2 = ToString<"阿寶哥" | 666 | true | -1234n>; // "阿寶哥" | "true" | "666" | "-1234"

圖片

對于上述的例子來說,其實并不復雜。但現在問題來了,如果傳入 EventName 或 Concat 工具類型的實際類型是聯合類型的話,那么結果又會是怎樣呢?接下來,我們來驗證一下:

type T3 = EventName<"foo" | "bar" | "baz">; 
// "fooChanged" | "barChanged" | "bazChanged"
type T4 = Concat<"top" | "bottom", "left" | "right">;
// "top-left" | "top-right" | "bottom-left" | "bottom-right"

圖片

為什么會生成這樣的類型呢?這是因為對于模板字面量類型來說,當類型占位符的實際類型是聯合類型(A |B |C)的話,就會被自動展開:

`[${A|B|C}]` => `[${A}]` | `[${B}]` | `[${C}]`

圖片

而對于包含多個類型占位符的情形,比如 Concat 工具類型。多個占位符中的聯合類型解析為叉積:

`${A|B}-${C|D}` => `${A}-${C}` | `${A}-${D}` | `${B}-${C}` | `${B}-${D}`

圖片

了解完上述的運算規則,你應該就能理解生成的 T3 和 T4 類型了。

在使用模板字面量類型的過程中,我們還可以使用 TypeScript 提供的,用于處理字符串類型的內置工具類型,比如 Uppercase、Lowercase、Capitalize 和 Uncapitalize。具體的使用方式是這樣的:

type GetterName<T extends string> = `get${Capitalize<T>}`;
type Cases<T extends string> = `${Uppercase<T>} ${Lowercase<T>} ${Capitalize<T>} ${Uncapitalize<T>}`;

type T5 = GetterName<'foo'>; // "getFoo"
type T6 = Cases<'bar'>; // "BAR bar Bar bar"

其實,模板字面量類型的能力是很強大的,結合 TypeScript 的條件類型和 infer 關鍵字我們還可以實現類型推斷。

type Direction = "left" | "right" | "top" | "bottom";
type InferRoot<T> = T extends `${infer R}${Capitalize<Direction>}` ? R : T;

type T7 = InferRoot<"marginRight">; // "margin"
type T8 = InferRoot<"paddingLeft">; // "padding"

圖片

在以上代碼中,InferRoot 工具類型除了利用模板字面量類型之外,還使用了 TypeScript 條件類型和 infer。如果你對這兩個知識點,還不了解的話,可以觀看 “用了 TS 條件類型,同事直呼 YYDS?” 和 “學會 TS infer,寫起泛型真香!” 這兩篇文章。

此外,TypeScript 4.1 版本允許我們使用 as 子句對映射類型中的鍵進行重新映射。它的語法如下:

type MappedTypeWithNewKeys<T> = {
[K in keyof T as NewKeyType]: T[K]
// ^^^^^^^^^^^^^
// This is the new syntax!
}

圖片

其中 NewKeyType 的類型必須是 string | number | symbol 聯合類型的子類型。在重新映射的過程中,結合模板字面量類型所提供的能力,我們就可以實現一些有用的工具類型。

比如,我們可以定義一個 Getters 工具類型,用于為對象類型生成對應的 Getter 類型:

type Getters<T> = {
[K in keyof T as `get${Capitalize<string & K>}`]: () => T[K]
};

interface Person {
name: string;
age: number;
location: string;
}

type LazyPerson = Getters<Person>;
// {
// getName: () => string;
// getAge: () => number;
// getLocation: () => string;
// }

圖片

在以上代碼中,因為 keyof  T 返回的類型可能會包含 symbol 類型,而 Capitalize 工具類型要求處理的類型需要是 string 類型的子類型,所以需要通過交叉運算符進行類型過濾。

除了實現簡單的工具類型之外,我們還可以實現比較復雜的工具類型。比如,用于獲取對象類型中,任意層級屬性的類型。

type PropType<T, Path extends string> = string extends Path
? unknown
: Path extends keyof T
? T[Path]
: Path extends `${infer K}.${infer R}`
? K extends keyof T
? PropType<T[K], R>
: unknown
: unknown;

declare function getPropValue<T, P extends string>(
obj: T,
path: P
): PropType<T, P>;

const obj = { a: { b: { c: 666, d: "阿寶哥" } } };
let a = getPropValue(obj, "a"); // { b: {c: number, d: string } }
let ab = getPropValue(obj, "a.b"); // {c: number, d: string }
let abd = getPropValue(obj, "a.b.d"); // string

圖片

在以上代碼中,PropType 工具類型涉及 TypeScript 中的多個核心知識點。

責任編輯:武曉燕 來源: 全棧修仙之路
相關推薦

2022-05-07 07:33:55

TypeScript條件類型

2022-04-29 06:54:48

TS 映射類型User 類型

2025-01-22 14:02:35

2021-10-09 07:10:30

Go字面量組合

2025-01-13 13:47:13

2022-05-30 16:31:08

CSS

2025-02-08 08:00:00

JavaDeepSeekIDEA

2020-09-27 10:55:10

代碼Java字符串

2021-03-04 09:31:42

開源技術 項目

2020-12-18 11:35:22

TypeScript語言Java

2024-01-30 09:21:29

CSS文字效果文字裝飾

2021-08-05 16:25:37

Windows 11Windows微軟

2023-12-10 20:33:50

Redis搜索全文

2021-02-03 20:19:08

Istio流量網格

2020-12-31 11:28:09

GitLabCICD

2025-06-09 01:22:00

2022-01-26 07:18:57

ES6WeakSetMap

2025-05-14 01:00:00

Spring工具工廠類

2025-04-02 04:55:00

2023-03-06 08:03:10

Python可視化工具
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美综合一区二区三区 | 福利片在线看 | 日日天天| 国产精品日韩欧美一区二区三区 | 99精品久久 | 亚洲v日韩v综合v精品v | 亚洲一区二区三区在线视频 | 久久69精品久久久久久久电影好 | 亚洲国产精品日本 | 亚洲综合免费 | 欧美精品片 | 97视频免费 | 欧美三级在线 | 亚洲一区二区三区免费在线观看 | 久久手机视频 | 夜久久| 国产精品视频一区二区三区 | 日韩欧美中文字幕在线观看 | 欧美精品福利视频 | 91视频一88av | 久久天天躁狠狠躁夜夜躁2014 | 岛国在线免费观看 | 国产99视频精品免视看9 | 免费在线国产视频 | 中国av在线免费观看 | 国产日韩欧美一区 | 操视频网站| 亚洲精品电影网在线观看 | 国内精品99 | 久久影音先锋 | 国产一区二区三区视频 | 国产精品美女久久久久久不卡 | 手机看片在线播放 | 天天操天天玩 | 91在线视频一区 | 日韩av成人 | 男人天堂网站 | 国产伦一区二区三区视频 | 91福利在线观看视频 | 综合久久99 | 91免费看片 |