持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第28天,点击查看活动详情
1. 引言
接着上一节中,接下来我们继续Ts中等篇的题型练习
https://github.com/type-challenges/type-challenges/blob/main/README.zh-CN.md 提供的TypeScript 类型体操姿势合集题型,目的是为了让大家更好的了解TS的类型系统,编写自己的类型工具,或者单纯的享受挑战的乐趣!
2. 题型
- 追加参数:实现一个泛型 AppendArgument<Fn, A>,对于给定的函数类型 Fn,以及一个任意类型 A,返回一个新的函数 G。G 拥有 Fn 的所有参数并在末尾追加类型为 A 的参数。
type Fn = (a: number, b: string) => number
type Result = AppendArgument<Fn, boolean>
// 期望是 (a: number, b: string, x: boolean) => number
思路:
使用infer关键字类比一个(...arg: infer T) => infer M 函数方法,通过(...arg: [...T,A]) => M 数组合并的方式返回包含新形参的一个新函数
解答:
type AppendArgument<Fn extends (...arg: any[]) => any, A> = Fn extends (...arg: infer T) => infer M ? (...arg: [...T,A]) => M : never
type Demo = AppendArgument<Case1,boolean> // type Demo = (arg_0: number, arg_1: string, arg_2: boolean, arg_3: boolean) => number
type Demo2 = AppendArgument<Case2,undefined> // type Demo2 = (arg_0: undefined, arg_1: undefined) => void
- Permutation:实现联合类型的全排列,将联合类型转换成所有可能的全排列数组的联合类型。
type perm = Permutation<'A' | 'B' | 'C'>; // ['A', 'B', 'C'] | ['A', 'C', 'B'] | ['B', 'A', 'C'] | ['B', 'C', 'A'] | ['C', 'A', 'B'] | ['C', 'B', 'A']
思路: 先判断是否空数组,在使用infer类型 解答:
type isNever<T> = [T] extends [never] ? true : false;
type Permutation<T, U = T> = isNever<T> extends true
? []
: T extends `${infer P}`
? [P, ...Permutation<Exclude<U, P>>]
: [];
- Length of String:计算字符串的长度,类似于 String#length 。
思路: 思路曲线:需要使用到extends,ingfer关键字拆解,再配合递归循环处理,把要计算的字符串变成数组,在通过T['length'] 获取字符串的长度。
解答:
type LengthOfString<S extends string,Arr extends any[] = []> = S extends `${infer M}${infer N}` ? LengthOfString<N,[...Arr,M]> : Arr['length']
type Demo = LengthOfString<''> // type Demo = 0
type Demo2 = LengthOfString<'kumiko'> // type Demo2 = 6
type Demo3 = LengthOfString<'reina'> // type Demo3 = 5
type Demo4 = LengthOfString<'Sound! Euphonium'> // type Demo4 = 16