【Typescript 系列】类型体操之中等篇题型(第六节)解读

121 阅读1分钟

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

1. 引言

接着上一节中,接下来我们继续Ts中等篇的题型练习 https://github.com/type-challenges/type-challenges/blob/main/README.zh-CN.md 提供的TypeScript 类型体操姿势合集题型,目的是为了让大家更好的了解TS的类型系统,编写自己的类型工具,或者单纯的享受挑战的乐趣!

2. 题型

  1. 追加参数:实现一个泛型 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

  1. 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>>]
	: [];
  1. 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