持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情
前言
在学习typescript的过程当中,有一个github库对其类型的学习特别有帮助,是一个有点类似于leetcode的刷题项目,能够在里面刷各种关于typescript类型的题目,本片文章带大家做其中简单难度的最后两道题 3060-easy-unshift 和 3312-easy-parameters
下面这个是类型体操github仓库:
3060-easy-unshift
我们首先还是先通过题目的README和测试case来看一下题目的要求
import type { Equal, Expect } from '@type-challenges/utils'
type cases = [
Expect<Equal<Unshift<[], 1>, [1]>>,
Expect<Equal<Unshift<[1, 2], 0>, [0, 1, 2 ]>>,
Expect<Equal<Unshift<['1', 2, '3'], boolean>, [boolean, '1', 2, '3']>>,
]
结合题目给的README和测试case,我们就能够得出,题目需要将传入的第二个类型并入第一个参数数组中去,这个用到了我们之前说到的数组解构,应该是很简单的。
利用js进行对比学习
题目中也说到了,这道题实现的是 JS 版本的 Array.unshift。我们可以先来了解一下这个方法的作用
可以看到这个方法的作用就是将参数并入数组当中,那么用 JS 的解构赋值也能够轻松的实现
实现 Unshift
这道题利用之前做过很多类似的类型体操,这里就不在过多的重复,使用 TS 的解构赋值就能够轻松实现。
需要注意一点的可能就是 JS 的 unshift 会将参数放在数组的第一位,所以我们结构的时候要把第二个泛型参数放到前面。
type Unshift<T extends unknown[], U> = [U, ...T];
这样测试case就都能够通过了。今天这天比较简单,一不做二不休,把简单题完结了,让我们来看下一题。
3312-easy-parameters
今天的第二题需要我们实现 TS 的内置工具类型 Parameters
import type { Equal, Expect } from "@type-challenges/utils";
const foo = (arg1: string, arg2: number): void => {};
const bar = (arg1: boolean, arg2: { a: "A" }): void => {};
const baz = (): void => {};
type cases = [
Expect<Equal<MyParameters<typeof foo>, [string, number]>>,
Expect<Equal<MyParameters<typeof bar>, [boolean, { a: "A" }]>>,
Expect<Equal<MyParameters<typeof baz>, []>>
];
那么我们首先要来看一下这个工具类型的作用。
内置工具类型 Parameters 的作用是拿到函数入参的类型,并且把所有入参的类型存放到一个元组中去。
const foo = (arg1: string, arg2: number): void => {};
type S = Parameters<typeof foo>;
// type S = [arg1: string, arg2: number]
利用js进行对比学习
JS 中并没有办法去获取到一个函数的入参是什么,但是我们可以利用到 JS 入参中,argument 伪数组的概念,通过这个数组,我们能够拿到 JS 中函数的入参数组。
那么在 TS 当中,是否也能够拿到这个数组呢,可以的话,就能够顺利解决题目中要拿到一个用入参组成的数组了。
实现 MyParameters
在 TS 的函数入参当中,我们可以声明一个 rest 参数,用于接收函数的所有入参,比如说按照我们正常定义函数的方法,我们一定要定义好每一个入参的类型:
type SD = (a:number,b:string)=>void
let a : SD = (a,s)=>{}
一旦入参大于现有的个数就会报错
那么类似的,我们可以声明一个 rest 参数,用于接收没有被定义的入参,它会是一个数组类型。
这样无论调用的时候传入了多少入参,都会被放入 rest 数组当中。
那么利用这一点,如果我们不定义入参的类型,而是只用一个 rest 参数去接收这些入参,并且通过 infer 来获取这个入参,那么是不是就能够拿到入参的元组类型了呢。
type MyParameters<T extends (...args: any) => any> = T extends (
...args: infer x
) => any
? x
: [];
const foo = (arg1: string, arg2: number): void => {};
type S = MyParameters<typeof foo>;
// type S = [arg1: string, arg2: number]
这样,我们就能够获取到入参的类型并且将它并入一个元组当中。
知识点
关于上述提到了部分的知识点:
- rest 参数
关于 rest 参数的部分可以优先参考官方文档,之后可能也会更加详细的来介绍它的相关知识。
总结
今天这道题的知识点设计到了 函数入参中的 rest 参数,这是 TS 提供给我们用来保存多余的入参的一个参数,之后会专门的去介绍一下这个参数的作用和注意事项。