TypeScript 类型体操之 Push、Unshift、Parameters、Get Return Type
这期是比较简单的几道题:
1、Push
在类型系统里实现通用的 Array.push
,例如:
type Result = Push<[1, 2], '3'> // [1, 2, '3']
新手注意,这里的 1
, 2
和 '3'
是类型,而不是值! 我们通过泛型和类型推断来实现一个类型级别(type-level)的 Array.push
操作。
实现:
type Push<T extends unknown[], U> = [...T, U];
// 使用示例
type OriginalArray = [1, 2, 3];
type ExtendedArray = Push<OriginalArray, 4>; // [1, 2, 3, 4]
Push
类型接受两个泛型参数 T
和 U
。T
必须是一个数组类型,而 U
可以是任意类型。Push
的结果是一个新的数组类型,它通过展开原始数组类型 T
并在末尾添加类型 U
来构造。
这里使用了 TypeScript 的扩展运算符(...
)来复制数组中的所有现有元素类型,并将新元素类型 U
添加到数组末尾。
再次说明:这个 Push
类型只是在类型层面上模拟了数组的 push
方法,它不会改变运行时的数组实例。在 TypeScript 中,类型层面的操作仅用于编译时的类型检查和推导,不会影响编译后的 JavaScript 代码的执行。
2、Unshift
实现类型版本的 Array.unshift
。
例如:
type Result = Unshift<[1, 2], 0> // [0, 1, 2,]
和 Push
一模一样的思路,不再解释:
type Unshift<T extends unknown[], U> = [U, ...T]
3、Parameters
实现内置的 Parameters 类型,而不是直接使用它,可参考TypeScript官方文档。
例如:
const foo = (arg1: string, arg2: number): void => {}
type FunctionParamsType = MyParameters<typeof foo> // [arg1: string, arg2: number]
在 TypeScript 中,内置的 Parameters
类型用于提取函数类型的参数类型,并将它们作为一个元组类型返回。如果我们完整学习了前面的题目,应该首先想到使用 infer
来实现。
在 TypeScript 中,infer
关键字用于在条件类型表达式中进行类型推断。infer
关键字通常与 extends
关键字一起使用,它允许你在条件类型的 extends
后面的语句中声明一个类型变量,并对该类型变量进行操作。这样,你可以捕获并使用在类型关系测试中推断出的类型。
实现如下:
type MyParameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;
// 使用示例
function exampleFunction(a: string, b: number, c: boolean): void {}
type Params = MyParameters<typeof exampleFunction>; // [string, number, boolean]
MyParameters
类型接受一个泛型参数 T
,它被约束为一个函数类型。然后,它使用条件类型来检查 T
是否可以赋值给一个具有参数 args
的函数类型,并使用 infer P
来推断 args
的类型。如果 T
是一个函数类型,MyParameters<T>
就会解析为参数的元组类型 P
。如果 T
不是一个函数类型,结果就是 never
。
4、Get Return Type
不使用 ReturnType
实现 TypeScript 的 ReturnType<T>
泛型。
ReturnType
用于获取函数的返回类型,实现思路同 Parameters
,具体如下:
type MyReturnType<T extedns (...args: any) => any> = T extends (...args: any) => infer R ? R : never;
总结
这四道题没有什么新的知识点,复习了类型的扩展运算符和 infer
的使用。
转载自:https://juejin.cn/post/7347154070539550770