TypeScript 中的模板字面类型:在类型检查期间的解析等

这篇博客主要介绍了 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};
  • 字符串操作实用类型

    • TypeScript 有四个内置的字符串操作类型UppercaseLowercaseCapitalizeUncapitalize,用于转换字符串大小写,如type _ = Assert<Equal< Uppercase<'hello'>, 'HELLO'>>;
    • 示例包括定义通用类型IsUppercaseToString用于将基本字面类型转换为字符串字面类型、修剪字符串字面量类型的Trim
  • 与元组的交互

    • 可连接字符串元组,如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 中定义 UUID 的类型type UUID = ${string}-${string}-${string}-${string}-${string};
    • 解析命令行参数,如{ episode: string; } & { keep: boolean; } & { ratio: string | boolean; }
    • document.querySelector()获取智能结果类型
    • 在 Angular 中进行路由类型定义
    • 用于 Express 路由提取
    • 定义 Tailwind 颜色变体类型
    • Arktype 库使用字符串字面量通过模板字面量类型来定义类型
  • 结论和注意事项

    • 模板字面量类型可用于静态检查复杂数据或推导类型,但存在错误消息不佳、代码难以理解、可能降低类型检查速度等问题
  • 进一步阅读

    • “Awesome Template Literal Types”列表
    • “Tackling TypeScript”中“An overview of computing with types”章节
  • 来源:TypeScript 手册章节“Template Literal Types”、Anders Hejlsberg 的拉取请求、Alexey Berezin 的博客、Alex MacArthur 的博客
阅读 12
0 条评论