TypeScript 字符串十二题例【进阶篇】

古早课件,未必完备。姑且写之,姑且看之。

TypeScript 字符串十二题例【基础篇】继续讨论:

题六:复制字符T为字符串类型,长度为C

type RepeatString<T extends string, 
C, 
A extends any[] = [], 
P extends string = ''> = 
C extends A['length'] ? P : RepeatString<T, C, [...A, null], `${P}${T}`>

type A = RepeatString<'a', 3> // 'aaa'
type B = RepeatString<'b', 2> // 'bb'
type C = RepeatString<'c', 1> // 'c'
type D = RepeatString<'d', 0> // ''
步骤解析
  1. 在TS类型与操作中,凡是涉及到数字类型的计算,基本上都要使用元组的长度
  2. 需要计算长度,所以我们需要一个元组(A)
  3. 还需要最后拼接的字符串,因此再设定一个字符串(P),默认为空字符串
  4. 通过判断元组的长度是否与给定的C相等来进行下一步操作
  5. 如果相等,就返回拼接好的字符串P
  6. 若果不相等,就继续将P与T拼接

整体思想还是使用递归,当元组长度未达到C时,我们往元组里面追加一个元素(任意,只要能让其长度+1)

题七:将字符串字面量类型按照指定字符,分割为元组。无法分割则返回原字符串字面量

type SplitString<T, S extends string, A extends any[] = []> = 
T extends `${infer L}${S}${infer R}` ? 
SplitString<R, S, [...A, L]> : [...A, T]

type A1 = SplitString<'linux.do', '.'>        // ["linux", "do"]
type A2 = SplitString<'hand-some', '-'>       // ["hand", "some"]
type A3 = SplitString<'linux.do', '-'>        // ["linux.do"]
步骤解析
  1. 还是拆分递归,只是本次将字符串拆分为三部分L、S、R
  2. 递归到最后一次LSR时,将当前的T(最后剩下的不含连接符的字符串)放入到A中
  3. 否则将R作为T继续遍历,直到最终不可拆分

题八:计算字符串字面量类型的长度

type LengthOfString<T, A extends any[] = []> = 
T extends `${infer L}${infer R}` ? 
LengthOfString<R, [...A, L]> : A['length']

type A = LengthOfString<'Linux.do'> // 8
type B = LengthOfString<''> // 0
步骤解析
  1. 老规矩,涉及到数字的运算,借助元组长度
  2. 如果可以拆分,则将L存入A中,继续递归
  3. 如果不可拆分,返回元组长度即可

题九:驼峰命名转烤串命名

type RemoveFirstHyphen<T> = T extends `-${infer L}` ? L : T

type KebabCase<T, P extends string = ''> = 
T extends `${infer L}${infer R}` ? 
KebabCase<R, `${P}${L extends Uppercase<L> ?
`-${Lowercase<L>}` : L}`> 
: RemoveFirstHyphen<P>

type a1 = KebabCase<'HandleOpenFlag'>           // handle-open-flag
type a2 = KebabCase<'OpenFlag'>                 // open-flag
步骤解析
  1. 遍历每一个字符,如果是大写就转为 连字符+小写
  2. 如果是小写,就返回自身,递归拼接
  3. 直到不能拆分为止,返回字符串P
  4. 最后借助 RemoveFirstHyphen 移除开头的连字符

题十:烤串命名转化为驼峰命名

// 方法一
export type CamelCase1<T extends string, S extends string = ''> = 
T extends `${infer L}-${infer R1}${infer R2}` ? 
CamelCase1<R2, `${S}${L}${Uppercase<R1>}`> : Capitalize<`${S}${T}`>

// 方法二
type CamelCase2<T extends string, S extends string = ''> = 
T extends `${infer L}-${infer R}` ? 
CamelCase2<R, `${S}${Capitalize<L>}`> : `${S}${Capitalize<T>}`

type a1 = CamelCase1<'handle-open-flag'>         // HandleOpenFlag
type a2 = CamelCase2<'open-flag'>                // OpenFlag
步骤解析
  • 方法一:拆分成 L-R1R2 的形式,将R1大写,进行拼接,最后将拼接好的字符串再首字母大写
  • 方法二:拆分成 L-R 形式,将L的首字母大写,最后剩下的T再执行首字母大写
  • 两种方法原理是一样的,拆分方法不同,都是遍历拼接
  • 借助了内置的Capitalize,也可以使用自己写的方法

9 个赞

最后两个实战题,明天再更。

3 个赞

感谢鹅佬的分享

3 个赞

太强了,大鹅!

3 个赞

大鹅,流批666:tieba_087:

2 个赞

鹅佬太强了!

2 个赞

这算是泛型体操吗:sob:

2 个赞

差不多吧 :tieba_087:

明天考试,答不上来关小黑屋

:tieba_087: 不要啊