这篇博客主要介绍了 TypeScript 中的模板字面量类型(template literal types),包括其语法、基本用法、字符串操作实用类型、与元组和对象的交互、实际应用案例以及一些有趣的使用方式等方面,具体内容如下:
语法和基本用法:
- 语法受 JavaScript 模板字面量启发,可连接值并插入静态字符串片段,如
type Song<Num extends number, Bev extends string> =
${Num} bottles of ${Bev};
- 连接是分布式的,可将字符串字面量联合类型插入模板字面量类型,得到笛卡尔积,如
type Modules = 'fs' | 'os' | 'path'; type Prefixed =
node:${Modules};
- 使用
infer
运算符可提取字符串部分,如type ParseSemver<Str extends string> = Str extends
${infer Major}.${infer Minor}.${infer Patch}? [ Major, Minor, Patch ] : never;
- 可插入其他类型进行字符串值约束,如
type Version =
v${number}.${number};
- 语法受 JavaScript 模板字面量启发,可连接值并插入静态字符串片段,如
字符串操作实用类型:
- TypeScript 有四个内置的字符串操作类型
Uppercase
、Lowercase
、Capitalize
、Uncapitalize
,用于转换字符串大小写,如type _ = Assert<Equal< Uppercase<'hello'>, 'HELLO'>>;
- 示例包括定义通用类型
IsUppercase
、ToString
用于将基本字面类型转换为字符串字面类型、修剪字符串字面量类型的Trim
等
- TypeScript 有四个内置的字符串操作类型
与元组的交互:
- 可连接字符串元组,如
type Join<Strs extends string[], Sep extends string = ','> = Strs extends [ infer First extends string,...infer Rest extends string[] ]? Rest['length'] extends 0? First :
${First}${Sep}${Join<Rest, Sep>}: '';
- 分割字符串,如
type Split<Str extends string, Sep extends string> = Str extends
${infer First}${Sep}${infer Rest}? [First,...Split<Rest, Sep>] : [Str];
- 示例包括将字符串字面量转换为字符串字面量联合、分割字符串为代码单元等
- 可连接字符串元组,如
与对象的交互:
- 可使用映射类型为对象属性名添加前缀,如
type PrependDollarSign<Obj> = { [Key in (keyof Obj & string) as
$${Key}]: Obj[Key] };
- 可使用映射类型为对象属性名添加前缀,如
实际应用案例:
- 在 Node.js 中使用
util.styleText()
进行样式化输出到终端,定义styleText()
函数进行样式字符串的静态检查,如styleText('bold+underline+red', 'Hello!');
- 处理属性路径,如
type PropType<T, Path extends string> = Path extends keyof T? T[Path] : Path extends
${infer First}.${infer Rest}? First extends keyof T? PropType<T[First], Rest> : unknown : unknown;
- 更改属性名前缀,如
type PropKeysAtToUnderscore<Obj> = { [Key in keyof Obj as AtToUnderscore<Key>]: Obj[Key] };
- 转换字符串大小写,如从驼峰命名法转换为短横线命名法
ToHyphenCase
和从短横线命名法转换为驼峰命名法ToLowerCamelCase
- 在 Node.js 中使用
有趣的使用方式:
- 在 Node.js 中定义 UUID 的类型
type UUID =
${string}-${string}-${string}-${string}-${string};
- 解析命令行参数,如
{ episode: string; } & { keep: boolean; } & { ratio: string | boolean; }
- 为
document.querySelector()
获取智能结果类型 - 在 Angular 中进行路由类型定义
- 用于 Express 路由提取
- 定义 Tailwind 颜色变体类型
- Arktype 库使用字符串字面量通过模板字面量类型来定义类型
- 在 Node.js 中定义 UUID 的类型
结论和注意事项:
- 模板字面量类型可用于静态检查复杂数据或推导类型,但存在错误消息不佳、代码难以理解、可能降低类型检查速度等问题
进一步阅读:
- “Awesome Template Literal Types”列表
- “Tackling TypeScript”中“An overview of computing with types”章节
- 来源:TypeScript 手册章节“Template Literal Types”、Anders Hejlsberg 的拉取请求、Alexey Berezin 的博客、Alex MacArthur 的博客
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。