Typescrip类型体操 - IndexOf
题目
中文
实现类型版本的 Array.indexOf
, indexOf<T, U>
接受一个数组T
和any
类型的U
作为参数, 返回T
中第一个U
的索引
type Res = IndexOf<[1, 2, 3], 2>; // expected to be 1
type Res1 = IndexOf<[2, 6, 3, 8, 4, 1, 7, 3, 9], 3>; // expected to be 2
type Res2 = IndexOf<[0, 0, 0], 2>; // expected to be -1
English
Implement the type version of Array.indexOf, indexOf<T, U> takes an Array T, any U and returns the index of the first U in Array T.
type Res = IndexOf<[1, 2, 3], 2>; // expected to be 1
type Res1 = IndexOf<[2, 6, 3, 8, 4, 1, 7, 3, 9], 3>; // expected to be 2
type Res2 = IndexOf<[0, 0, 0], 2>; // expected to be -1
答案
注释中包含了部分解析
// ✅
type IsEqual<X, Y> = (<F>() => F extends X ? 1 : 0) extends <F>() => F extends Y ? 1 : 0
// `IsEqual`的错误写法
// ❌`IsEqualMistake<any, string>`期望返回`true`, 实际是`boolean`, 发生了`distribute`
type IsEqualMistake<L, R> = L extends R ? (R extends L ? true : false) : false;
type IsEqualMistake1<L, R> = [
L extends R ? 1 : 0,
R extends L ? 1 : 0
] extends [1, 1]
? true
: false;
// ❌ 另一种写法错误写法
// 虽然是错误写法, 但是有个知识点:
// 💡 使用`[]`可以防止发生[`distribute`](https://www.typescriptlang.org/docs/handbook/2/conditional-types.html#distributive-conditional-types)
type IsEqualMistake2<L, R> = [Exclude<L, R>, Exclude<R, L>] extends [
never,
never
]
? true
: false;
type IndexOf<T extends any[], U extends any, S extends any[] = []> = T extends [
infer L,
...infer R
]
? true extends IsEqual<L, U>
? S['length']
: IndexOf<R, U, [...S, 0]>
: -1;