TS类型体操 之 字符串的妙用

7/3/2022

# TS 类型体操 之 字符串的妙用

这里记录一下做题过程中遇到的一些字符串处理比较巧妙的技巧,后面主要引入的题目是 00529-medium-absolute (opens new window)

对于字符串的用法,前置知识的篇章已经介绍过了,例子如下。理解了这部分例子后相信可以解决很多的题目了

type testInfer<T extends string> = T extends `${infer F}${infer S}${infer R}` ? [F, S, R] : T

type testInfer1 = testInfer<'123456'>
// 按照占位符的特性,前面F和S分别占据2个字符,剩余的都给R占去了
// type testInfer1 = ["1", "2", "3456"]

// 稍作改动,在S占位符后面添加一个5
type testInfer2<T extends string> = T extends `${infer F}${infer S}5${infer R}` ? [F, S, R] : T
type testInfer3 = testInfer<'123456'>
// F 占第一个字符 = 1
// S 占据2-4,因为在R之前有一个5,所以S代表了第二个字符开始到5的所有字符
// 那么R就是从5开始,到末尾,所以得出的结果如下:
// type testInfer1 = ["1", "234", "6"]
1
2
3
4
5
6
7
8
9
10
11
12
13

# 00529-medium-absolute 题目详解

需求:实现一个接收 string,number 或 bigInt 类型参数的 Absolute 类型,返回一个正数字符串。

  • 接收 string,number,或者 bigInt
  • 返回正整数
  • 返回字符串

挑几个代表性的测试用例

type testcase = Absolute<0>
type testcase = Absolute<-5>
type testcase = Absolute<'0'>
type testcase = Absolute<'-0'>
type testcase = Absolute<'10'>
type testcase = Absolute<-1_000_000n>
type testcase = Absolute<9_999n>
1
2
3
4
5
6
7

# 解题思路

思路 1: 比较绕的思路

  • 把数字都先转换为字符串
  • 逐个字符串比较(使用 infer 提取每个字符串,然后比较,比较成功后存储到一个变量 R 中)
  • 当传入的字符串为空后返回变量 R

思路 1 实现:

type NumberStr = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'

type Absolute<T extends number | string | bigint, R extends string = ''> = `${T}` extends `${infer F}${infer Rest}`
  ? F extends NumberStr
    ? Absolute<Rest, `${R}${F}`>
    : Absolute<Rest, R>
  : R
1
2
3
4
5
6
7

其中,当传入的泛型 T 可能是 number 或者 bigInt 类型的时候,无法直接用 extends xxx

所以一开始的技巧就是 ${T} 把不管是不是字符串类型的,都转换为字符串(这也是因为数字类型可以转字符串)

剩下的就是逐个字符比较。


思路 2: 利用数字特性,比如 1_000_000n 在程序 tostring 的时候其实会自动转换为 1000000,并不用我们考虑太多去除 \_ 或者 去除n 的逻辑

思路 2 实现:

type Absolute<T extends number | string | bigint> = `${T}` extends `-${infer Num}` ? Num : `${T}`
1

这种方法直接匹配传入的内容是不是带有 -

  • 没有的话,说明是正整数(有可能是数字)所以包裹一层`` 直接当作字符串输出
  • -号的话,利用 infer 和 字符串的特性,排除第一个-,剩下的就都是对应数字的字符串了

# 小结

  • 在匹配过程中,可以使用 ${T} 的语法,把 number 也转换为字符串
  • 数字类型,包括 bigInt 类型转换的时候其实会自动转换为数字,利用该特点还能少写点代码
Last Updated: 1/7/2024, 5:51:59 PM