第 79 期 - TypeScript 字符串操作:模板字面量类型的应用
logoFRONTALK AI/1月11日 16:30/阅读原文

摘要

文章阐述了 TypeScript 4.1 版本后的模板字面量类型,通过联合类型、infer 关键字和递归,展示了在字符串操作中的应用,如定义类型、提取部分内容、替换字符等,并修正操作中的错误。

一、TypeScript 的模板字面量类型基础示例

在 TypeScript 4.1 版本后,可以使用模板字面量语法操作字符串。例如定义InternalRoute类型为/${string},这样函数goToRoute的参数route只能接收以/开头的字符串,否则会报错。这展示了模板字面量类型在简单的字符串类型定义上的应用。

二、模板字面量类型中的联合类型

  1. 可以在模板字面量类型中使用联合类型来扩展成更大的联合类型。例如EntityAttributes类型定义为${'post' | 'user'}${'Id' | 'Name'},其结果是'postId' | 'userId' | 'postName' | 'userName'。这体现了联合类型在模板字面量类型中的组合效果。

三、模板字面量类型中的 infer 关键字

  1. 可以在模板字面量中使用infer关键字。如GetLastName类型定义中,TFullName extends ${infer TFirstName} ${infer TLastName}? TLastName : never,对于像Matt Pocock这样有空格分隔的字符串,infer会将其拆分为类型变量TFirstNameTLastName,然后通过? TLastName返回最后一个名字。例如type Pocock = GetLastName<'Matt Pocock'>,结果为"Pocock"
  2. 对于更复杂的需求,如将名字中的空格替换为破折号。定义ReplaceSpaceWithDash类型,TFullName extends ${infer TFirstName} ${infer TLastName}? ${TFirstName}-${TLastName} : never,例如type Name = ReplaceSpaceWithDash<'Emmylou Harris'>,结果为"Emmylou - Harris"
  3. 为了让代码更通用,对类型变量重命名,将TFullName改为TStringTFirstName改为TPrefixTLastName改为TSuffix

四、实现更通用的字符串替换类型

  1. 定义Replace类型来实现更通用的字符串替换,type Replace<TString extends string, TToReplace extends string, TReplacement extends string>,当TString extends ${infer TPrefix}${TToReplace}${infer TSuffix}时,返回${TPrefix}${TReplacement}${TSuffix},否则返回never。例如type DashName = Replace<'Matt Pocock', ' ', '-'>,结果为"Matt - Pocock"`。
  2. 但是这个类型存在两个问题,一是如果没有找到要替换的字符串会返回never,这是不正确的,修改后的Replace类型在没有找到要替换的字符串时返回传入的字符串。例如type Result = Replace<'Matt', ' ', '-'>,结果为"Matt"
  3. 第二个问题是只替换一次,如果有多个要替换的字符串实例,后面的将被忽略。例如type DashCaseName = Replace<'Matt Pocock III', ' ', '-'>,结果为"Matt - Pocock III"

五、通过递归解决多次替换问题

  1. 定义StringReplace类型,通过递归调用解决多次替换的问题。type StringReplace<TString extends string, TToReplace extends string, TReplacement extends string>,当TString extends ${infer TPrefix}${TToReplace}${infer TSuffix}时,返回${TPrefix}${TReplacement}${StringReplace<TSuffix, TToReplace, TReplacement>},否则返回TString。例如type Result = StringReplace<'Matt Pocock III', ' ', '-'>,结果为"Matt - Pocock - III"`。
  2. 在递归过程中,要注意避免无限循环。以StringReplace<"Matt Pocock III", " ", "-">为例,第一次返回Pocock III,第二次返回III,最后因为找不到" ",直接返回TString(这里是"III"),从而结束递归循环。
 

扩展阅读

Made by 捣鼓键盘的小麦 / © 2025 Front Talk 版权所有