「这是我参与2022首次更文挑战的第13天,活动详情查看:2022首次更文挑战」
前言
在学习typescript的过程当中,有一个github库对其类型的学习特别有帮助,是一个有点类似于leetcode的刷题项目,能够在里面刷各种关于typescript类型的题目,本片文章带大家做其中简单难度的第四道题 14-easy-firs
14-easy-firs
首先还是先来看一下题目的README来看一下题目的要求
type cases = [
Expect<Equal<First<[3, 2, 1]>, 3>>,
Expect<Equal<First<[() => 123, { a: string }]>, () => 123>>,
Expect<Equal<First<[]>, never>>,
Expect<Equal<First<[undefined]>, undefined>>
]
结合题目给的README和测试case,我们能发现这次要实现的函数为 First<T>,接收一个数组并且返回第一个元素。
在测试中,我们能看到,进入数组为 [3,2,1] 则返回一个 3,并且还能返回一个函数,注意在空数组的情况下将会返回一个 never
接下来我们就开始做题
利用js进行对比学习
首先我们还是先用js来模拟题目的要求。
这次题目的要求用js来模拟就非常简单,我们接收一个数组,并且返回数组的第一项,要注意当数组为空的时候返回 never
// js
const first = (arr) => {
if(arr.length == 0) return "never"
return arr[0];
};
实现 First
接着我们就按照js的逻辑来实现ts的代码
- 将传入数组的第一项返回出去:
type First<T extends any[]> = T[0]
意料之中测试的never出错了:
但是如果传入的是一个空的数组,那如果不加任何的判断,将会返回一个 undefined 类型:
这就和题目要求的 never 不同,所以接下来我们只要实现这一步判断。
1.通过 extends 判断
在 ts 中的 extends 可以被用来作为一种约束,我们可以用它来约束我们的数组:
type First<T extends any[]> = T extends [] ? never : T[0];
2.通过 extends 和 'length' 判断
在上面的 js 当中,我们常见的可以通过数组的长度是否为 0 来判断一个数组是否是空数组,当然在 ts 中也能够这样添加判断,我们只需要去读取数组中的 'length' 属性:
type First<T extends any[]> = T["length"] extends 0 ? never : T[0];
3.通过 extends 和 [number] 判断
在之前我们有提到过,通过 T[number] 的方式,我们能遍历传入的数组,但是如果传入的数组为空的话,那么遍历的值会是什么呢
这场情况下为 union 类型
是不是发现了,在空数组的情况下,返回的是一个 never 类型,而不是上面的 undefined 类型,这是因为我们上面指定了位置为 0 的元素,而在下面的方式中并没有,而是返回了整个数组的类型,通过这个,我们就能够结合 extends 写出第三种题解
type First<T extends any[]> = T[0] extends T[number] ? T[0] : never
正常情况下的 T[0] 肯定是会存在于 T[number] 中的,但是当数组为空的时候 T[0] 为 undefined ,就不包含在 T[number] 的 never 中了。
4. inter(推断) 的使用
这里可以使用一个新的知识点,我们可以使用 inter 来做一个解题, inter 的使用有点类似于 es6 的解构赋值。
const [first, ...rest] = arr;
在 es6 中我们可以像上面一样去获取一个数组中的第一个元素也就是 first,剩下的元素就为 rest。
那么在 ts 中也一样
type First<T extends any[]> = T extends [infer First, ...infer Rest]
? First
: never;
First 就是输入数组的第一个元素,其余元素都为 Rest,我们只需要拿到 First 的值就可以了。
知识点
关于上述提到了部分的知识点:
- inter(推断) 今天主要的新知识点就是 inter(推断) ,关于这个知识点我暂时没有找到相关的文档,只有一些文章教了如何去使用,具体的使用文档可以去官方找找看有没有。
TypeScript: Documentation - TypeScript 3.9 (typescriptlang.org)
总结
今天我们用了4种方法来解决第四道题,并且利用到了很多以后才会涉及到的知识点,这里可以多加理解一下4种不同的解题方式。