搞定TS,就靠这个系列!(三)

1,254 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

序言:

这是搞定 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 (获取函数的参数类型)。
  2. ReturnType (获取函数的返回值类型)。
  3. 对 infer 的使用

题解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']]]]]>

这题其实是上面的衍生题,主要就是利用递归实现多维数组的展开