Skip to content

LastIndexOf

约 449 字大约 2 分钟

2022-12-01

题目

实现类型版本的 Array.lastIndexOf, LastIndexOf<T, U> 接受数组 T, any 类型 U, 如果 U 存在于 T 中, 返回 U 在数组 T 中最后一个位置的索引, 不存在则返回 -1

type Res1 = LastIndexOf<[1, 2, 3, 2, 1], 2> // 3
type Res2 = LastIndexOf<[0, 0, 0], 2> // -1

解题思路

本挑战的难点在于 如何判断一个类型是否严格等于另一个类型。

对于此难点,请参考 类型系统的真假美猴王:破解 IsEqual<X, Y> 之谜

通过 条件类型 infer,从数组 T 中,通过递归的方式取出一个个元素,判断是否严格等于类型 U, 如果是,则直接返回 R['length'] 的长度,否则继续递归取下一个元素,并为 R 添加一个元素。

递归时,类型R 的剩余数组长度,恰好为 T 的最后一个元素的索引。

答案

type Equal<X, Y> =
  (<T>() => T extends X ? 1 : 2) extends
  (<T>() => T extends Y ? 1 : 2) ? true : false

type LastIndexOf<T extends unknown[], U> = T extends [...infer R, infer F]
  ? Equal<F, U> extends true
    ? R['length']
    : LastIndexOf<R, U>
  : -1

验证

type 
cases
= [
Expect
<
Equal
<
LastIndexOf
<[1, 2, 3, 2, 1], 2>, 3>>,
Expect
<
Equal
<
LastIndexOf
<[2, 6, 3, 8, 4, 1, 7, 3, 9], 3>, 7>>,
Expect
<
Equal
<
LastIndexOf
<[0, 0, 0], 2>, -1>>,
Expect
<
Equal
<
LastIndexOf
<[string, 2, number, 'a', number, 1], number>, 4>>,
Expect
<
Equal
<
LastIndexOf
<[string, any, 1, number, 'a', any, 1], any>, 5>>,
]

参考