TypeScipt 每日类型挑战 - 使用TypeScript实现类型<Trim>

409 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第11天,点击查看活动详情

小试牛刀

为了解决这个问题,首先我们来解决TrimLeft<T> ,该类型用于接收确定的字符串类型并返回一个新的字符串,其中新返回的字符串删除了原字符串开头的空白字符串。

例如

type trimed = TrimLeft<'  Hello World  '> // 应推导出 'Hello World  '

解答

  • 首先明确该类型的功能:移除字符串开头的空白字符串。
  • 其次,要定义字符串开头的空白,即:
type Space = ' ' | '\n' | '\t'
  • 最后,字符串左侧开头的空白字符可能不止一个,需要递归地进行处理。

最终代码:

type Space = ' ' | '\n' | '\t'

type TrimLeft<S extends string> = S extends `${Space}${infer R}` ? TrimLeft<R> : S

infer关键字总结:

  1. 作用:类型推导,在类型未推导时进行占位,等到真正推导成功后,它能准确地返回正确的类型

  2. 注意点:

  • infer只能在 extends 条件语句中使用,声明变量只能在true分支中使用
  • 对使用了函数重载的函数进行类型推断时,以最后一个签名为准,因为一般这个签名是用来处理所有情况的签名。
  • infer在协变的位置上时,同一类型变量的多个候选类型将会被推断为联合类型;当infer在逆变的位置上时,同一类型变量的多个候选类型将会被推断为交叉类型。

进阶

既然实现了<Trimleft>, 那么<TirmRight>呢?区别只是在于空白字符是在左侧进行占位还是在右侧进行占位。

type Trim<S extends string> = S extends (`${Space}${infer R}` | `${infer R}${Space}`) ? Trim<R> : S

那么<Tirm>呢,同时去掉输入字符串的左侧空白和右侧空白,现在就很简单了,只要将<Trimleft><Trimright>结合一下就好了。

type Space = ' '  | '\n' | '\t'
type Trim<S extends string> = S extends `${Space}${infer R}` | `${infer R}${Space}` ? Trim<R> : S

可以自己动手尝试一下:here

参考