LastIndexOf
挑战
在类型系统中实现 Array.lastIndexOf
。 LastIndexOf<T, U>
接收一个数组 T
和查
找项 U
,并且返回 U
在数组 T
中最后一次出现位置的索引,例如:
type Res1 = LastIndexOf<[1, 2, 3, 2, 1], 2>; // 3
type Res2 = LastIndexOf<[0, 0, 0], 2>; // -1
解答
要找到元素在元组中最后一次出现位置的索引,只需要从右往左枚举元组项直至找到匹配 项。然后获取匹配项的索引。听起来很简单,让我们开始吧。
像往常一样,我们从一个空白类型开始:
type LastIndexOf<T, U> = any;
在这个类型中,我们有 T
和 U
两个泛型,T
是元组,U
是我们要查找的项。让我
们从条件类型开始,我们将元组推断为两个部分。一部分是最后一项(I
),另一部分是
前面的剩余项(R
):
type LastIndexOf<T, U> = T extends [...infer R, infer I] ? never : never;
一旦我们推断出最右侧的项,我们就可以检查它是否和我们要查找的项相等。我们可以使用
一个内置的工具类型 Equal
来协助我们完成检查:
type LastIndexOf<T, U> = T extends [...infer R, infer I]
? Equal<I, U> extends true
? never
: never
: never;
如果找到了匹配项意味着什么呢?意味着我们找到了要查找的项,但是如何获取其索引呢? 左侧剩余项元组的长度,正好就是我们需要的索引,是吗?所以我们使用左侧剩余项元组的 长度当做索引:
type LastIndexOf<T, U> = T extends [...infer R, infer I]
? Equal<I, U> extends true
? R["length"]
: never
: never;
如果找不到匹配项,我们就继续递归寻找下去:
type LastIndexOf<T, U> = T extends [...infer R, infer I]
? Equal<I, U> extends true
? R["length"]
: LastIndexOf<R, U>
: never;
最后,如果仍然没有找到匹配项,则返回 -1
作为答案:
type LastIndexOf<T, U> = T extends [...infer R, infer I]
? Equal<I, U> extends true
? R["length"]
: LastIndexOf<R, U>
: -1;
评论