持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第13天,点击查看活动详情
前言
在学习typescript的过程当中,有一个github库对其类型的学习特别有帮助,是一个有点类似于leetcode的刷题项目,能够在里面刷各种关于typescript类型的题目,在上一篇文章中,我们完成了中等的第六题,今天来做中等的第七题 15-medium-last
下面这个是类型体操github仓库:
15-medium-last
import type { Equal, Expect } from '@type-challenges/utils'
type cases = [
Expect<Equal<Last<[3, 2, 1]>, 1>>,
Expect<Equal<Last<[() => 123, { a: string }]>, { a: string }>>,
]
从README和测试用例中能够得出,题目需要我们实现一个工具类型 Last,用于获取数组的最后一个元素。
利用 JS 进行对比学习
1. 数组最后一个索引
首先最简单的方法,通过返回数组的最后一个索引来获得最后一个元素。
function last(arr) {
return arr[arr.length-1]
}
递归判断
利用递归判断当前的数组的个数,一个的话直接返回,超过一个就去掉首位,将剩下的数组再次放入方法当中。
function last(arr) {
if(arr.length == 1){
return arr[0]
}else{
arr.shift()
return last(arr)
}
}
实现 Last
通过 JS 的实现,我们大概能够得到几个思路,一个是通过数组的长度来获取最后一个元素,另一个是通过递归来一个一个的剔除掉第一个元素,直到拿到最后一个元素。
通过数组的 'length' 属性实现
通过索引类型我们就能够拿到数组的某一个位置的值,并且TS中也是能够通过length这个属性来获取长度的:
type GetLength<T extends any[]> = T['length']
type B1 = GetLength<[() => 123, { a: string }]>
// type B1 = 2
但是存在一个问题,数组的长度并不是数组的最后一项的下标,但是再 TS 中我们没办法执行减一这样的操作。
type Last<T extends any[]> = T[T['length']]
type B1 = Last<[() => 123, { a: string }]>
// type B1 = undefined
但是我们能够稍微取巧一下,我给当前这个数组最前面加一项不就可以了吗,并且我们能够通过解构赋值,很方便的完成这一步。
type Last<T extends any[]> = [any , ...T][T['length']]
type B1 = Last<[() => 123, { a: string }]>
// type B1 = {
// a: string;
// }
这里的第一项只是一个占位符,是什么类型都是无所谓的,他只是为了让我们把最后一项的下标变成数组长度,这样子,我们就能够拿到最后一项了。
通过递归实现
JS 的解法中还有另外一种,就是通过不断地移除掉第一个元素并且递归,实现到最后数组中只剩下一个元素来获取,这个元素就是末尾的元素。
在 TS 中我们能够通过 infer 关键字来获取数组中的第一个元素和后面的数组,只需要去判断一下当前数组中是不是只有一个元素,不是的话将后面的数组丢入递归,是的话就返回这个唯一的元素。
type Last<T extends any[]> = T extends [infer R]
? R
: T extends [infer first,...infer rest]
? Last<rest>
: never
type B1 = Last<[() => 123, { a: string }]>
// type B1 = {
// a: string;
// }
infer + 解构
在上面的那一种实现方法中,我们是通过infer来获取数组的第一项,但是 infer 加 解构 不止是能获取第一项,还可以获取到数组的末尾项,其中的写法和取第一项是完全一样的。
type Last<T extends any[]> = T extends [...infer R, infer rest]
? rest
: never;
这样子,我们也能够顺利的拿到了数组的最后一项
知识点
关于上述提到了部分的知识点:
- 解构赋值
- 数组的 'length' 属性
- infer 关键字
本文共用了三种不同的解法来解答了这道题,题目涉及到的知识点大部分都是重复的,在这里就不再过多的重复了,不懂得小伙伴能够取阅读一下之前的相关文章。
总结
今天我们做完了中等的第七题,题目的解法很多,但是大部分知识点我们都是碰到过的,只是在于你是否能够灵活的运用,这点就是算法题的精髓所在,语法都在这里,但是会不会用,就是另一回事了。