小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
序言:
这是搞定 TS 第三篇,如果没有基础的小伙伴想要从零搞定 TS ,请从第一篇开始juejin.cn/post/701033…
第一题
定义一个工具类型,AppendArgument ,为一个函数类型,增加指定类型的参数,新增加的参数名字为 x ,将作为新函类型的第一个参数,案例如下
type Fn = (a: number, b: string) => number
type AppendArgument<F, A> = // 你的实现代码
type FinalFn = AppendArgument<Fn, boolean>
// (x: boolean, a: number, b: string) => number
本题考查内容:
题解1
使用 Parameters 和 ReturnType ,如果不了解,下面有详细解释。
type AppendArgument<F extends (...args: any) => any, A>
= (x: A, ...args: Parameters<F>) => ReturnType<F>
type Fn = (a: number, b: string) => number
type FinalF = AppendArgument<Fn, boolean>
// (x: boolean, a: number, b: string) => number
首先定义好原先的 Fn 和 我们新定义的参数 A ,然后用 Parameters 将原先的参数类型取出,赋值给原先的参数,最后用 RetrnType 返回结果类型。
知识点补充
Parameters
declare function f1(arg: { a: number; b: string }): void;
type T0 = Parameters<() => string>;
type T0 = []
type T1 = Parameters<(s: string) => void>;
type T1 = [s: string]
type T2 = Parameters<<T>(arg: T) => T>;
type T2 = [arg: unknown]
type T3 = Parameters<typeof f1>;
type T3 = [arg: {
a: number;
b: string;
}]
通过上例我们可以知道, Parameters 接受一个function 参数或者是 typeof Fn ,返回的是该函数的参数类型。
ReturnType
declare function f1(): { a: number; b: string };
type T0 = ReturnType<() => string>;
type T0 = string
type T1 = ReturnType<(s: string) => void>;
type T1 = void
type T2 = ReturnType<<T>() => T>;
type T2 = unknown
type T3 = ReturnType<<T extends U, U extends number[]>() => T>;
type T3 = number[]
type T4 = ReturnType<typeof f1>;
type T4 = {
a: number;
b: string;
}
ReturnType 同样接受一个 Fn,构造一个由 function 的返回类型组成的类型Type。
第二题
定义一个 NativeFlat 工具类型,支持把数组类型拍平(扁平化)。具体的使用示例如下所示:
type NaiveFlat<T extends any[]> = // 你的实现代码
// 测试用例:
type NaiveResult = NaiveFlat<[['a'], ['b', 'c'], ['d']]>
// NaiveResult的结果: "a" | "b" | "c" | "d"
在完成 NaiveFlat 工具类型之后,在继续实现 DeepFlat 工具类型,以支持多维数组类型:
type DeepFlat<T extends any[]> = unknown // 你的实现代码
// 测试用例
type Deep = [['a'], ['b', 'c'], [['d']], [[[['e']]]]];
type DeepTestResult = DeepFlat<Deep>
// DeepTestResult: "a" | "b" | "c" | "d" | "e"
本题考查内容
要数组扁平化,typeof ArrayInstance[number] ,通过数组值获取对应类型
题解 NativeFlat
type NaiveFlat<T extends any[]> = {
[P in keyof T ] : T[P] extends any[] ? T[P][number] : T[P]
}[number]
//NaiveResult = ["a", "b" | "c", "d"][number]
type NaiveResult = NaiveFlat<[['a'], ['b', 'c'], ['d']]>
// NaiveResult: "a" | "b" | "c" | "d" | "e"
本题的思路并不复杂,首先拿到每一项,然后判断这项是否为数组,如果是就用 [number] 这种方法将他转换为联合类型,最后返回的是一个一元数组,我们的目标是返回联合类型,所以还需要使用一次[number] 将结果的一元数组再转换成联合类型
题解 DeepFlat
type DeepFlat<T extends any[]> = {
[P in keyof T ] : T[P] extends any[] ? DeepFlat<T[P]>: T[P]
}[number]
type DeepFlatResult = DeepFlat<[['a'], ['b', 'c'], [['d']], [[[['e']]]]]>
这题其实是上面的衍生题,主要就是利用递归实现多维数组的展开