您现在的位置是:亿华云 > 域名
用了模板字面量类型,同事直呼太强了!
亿华云2025-10-04 03:57:03【域名】0人已围观
简介你了解过模板字面量类型么?你想知道如何利用模板字面量类型,来减少 TypeScript 项目中的重复代码么?如果想的话,阅读完本文内容之后,也许你就懂了。假设我们想要定义一种类型来描述 CSS pad
你了解过模板字面量类型么?用模你想知道如何利用模板字面量类型,来减少 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
type Concat
type ToString
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
type Cases
type T5 = GetterName
其实,模板字面量类型的能力是很强大的,结合 TypeScript 的条件类型和 infer 关键字我们还可以实现类型推断。
type Direction = "left" | "right" | "top" | "bottom";
type InferRoot
type T7 = InferRoot<"marginRight">; // "margin"
type T8 = InferRoot<"paddingLeft">; // "padding"在以上代码中,InferRoot 工具类型除了利用模板字面量类型之外,还使用了 TypeScript 条件类型和 infer。如果你对这两个知识点,还不了解的话,可以观看 “用了 TS 条件类型,同事直呼 YYDS” 和 “学会 TS infer,写起泛型真香!源码下载” 这两篇文章。
此外,TypeScript 4.1 版本允许我们使用 as 子句对映射类型中的键进行重新映射。它的语法如下:
type MappedTypeWithNewKeys
[K in keyof T as NewKeyType]: T[K]
// ^^^^^^^^^^^^^
// This is the new syntax!
}其中 NewKeyType 的类型必须是 string | number | symbol 联合类型的子类型。在重新映射的过程中,结合模板字面量类型所提供的能力,我们就可以实现一些有用的工具类型。
比如,我们可以定义一个 Getters 工具类型,用于为对象类型生成对应的 Getter 类型:
type Getters
[K in keyof T as `get${ Capitalize
};
interface Person {
name: string;
age: number;
location: string;
}
type LazyPerson = Getters
// {
// getName: () => string;
// getAge: () => number;
// getLocation: () => string;
// }在以上代码中,因为 keyof T 返回的类型可能会包含 symbol 类型,而 Capitalize 工具类型要求处理的类型需要是 string 类型的子类型,所以需要通过交叉运算符进行类型过滤。
除了实现简单的工具类型之外,我们还可以实现比较复杂的工具类型。比如,用于获取对象类型中,任意层级属性的类型。
type PropType
? unknown
: Path extends keyof T
? T[Path]
: Path extends `${ infer K}.${ infer R}`
? K extends keyof T
? PropType
: unknown
: unknown;
declare function getPropValue
obj: T,
path: P
): PropType
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 中的多个核心知识点。
很赞哦!(862)
相关文章
- 为了避免将来给我们的个人站长带来的麻烦,在选择域名后缀时,我们的站长最好省略不稳定的后缀域名,比如n,因为我们不知道策略什么时候会改变,更不用说我们将来是否还能控制这个域名了。因此,如果站长不是企业,或者有选择的话,如果不能选择域名的cn类,最好不要选择它。
- Hystrix降级逻辑中如何获取触发的异常
- HashMap中傻傻分不清楚的那些概念
- 学生自学Python去面试,月薪为何仅3K?面试官问题解析!
- 众所周知,com域名拥有最大的流通市场和流通历史。最好选择com域名,特别是在购买域名时处理域名。其次可以是cn域名、net域名、org域名等主流域名,现在比较流行的王域名和顶级域名,都是值得注册和投资的。
- 麦肯锡报告:AI时代学什么稳赚不赔?编程,编程,编程
- 可代替 Dropbox 的 5 个开源软件
- 程序员能不能一直纯靠技术生存
- 3、商标域名一经注册,就可以作为域名裁决过程中的主要信息之一。这可以大大增加公司被抢注的相关域名胜诉的机会。
- 保证DevOps与持续交付质量的九大测试工具