古早课件,未必完备。姑且写之,姑且看之。
从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> // ''
步骤解析
- 在TS类型与操作中,凡是涉及到数字类型的计算,基本上都要使用元组的长度
- 需要计算长度,所以我们需要一个元组(A)
- 还需要最后拼接的字符串,因此再设定一个字符串(P),默认为空字符串
- 通过判断元组的长度是否与给定的C相等来进行下一步操作
- 如果相等,就返回拼接好的字符串P
- 若果不相等,就继续将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"]
步骤解析
- 还是拆分递归,只是本次将字符串拆分为三部分L、S、R
- 递归到最后一次LSR时,将当前的T(最后剩下的不含连接符的字符串)放入到A中
- 否则将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
步骤解析
- 老规矩,涉及到数字的运算,借助元组长度
- 如果可以拆分,则将L存入A中,继续递归
- 如果不可拆分,返回元组长度即可
题九:驼峰命名转烤串命名
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
步骤解析
- 遍历每一个字符,如果是大写就转为 连字符+小写
- 如果是小写,就返回自身,递归拼接
- 直到不能拆分为止,返回字符串P
- 最后借助 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,也可以使用自己写的方法