为了推断所有类型,您应该将as const 用于arr,或者将其作为文字类型传递给函数而不是传递引用。
type FindIndex<
T extends Array<{ type: string }>,
ExpectedType extends T[number]['type'],
> = {
[Prop in keyof T]:
(T[Prop] extends { type: infer Type }
? (Type extends ExpectedType
? Prop
: never
)
: never
)
}[number];
{
// 0
type Test = FindIndex<[{ type: 'a' }, { type: 'b' }], 'a'>
}
function GetType<
Type extends string,
Elem extends { type: Type },
Arr extends Elem[],
ExpectedType extends Arr[number]['type'],
>(arr: [...Arr], type: ExpectedType): FindIndex<Arr, ExpectedType>
function GetType<
Arr extends { type: string }[],
ExpectedType extends Arr[number]['type'],
>(arr: [...Arr], type: ExpectedType) {
return arr.find((item) => item.type === type)
}
const result = GetType([{ type: 'a' }, { type: 'b' }], 'a') // 0
说明
FindIndex - 遍历文字推断的元组/数组并检查type 属性是否扩展ExpectedType。如果是 - 返回Prop,在我们的例子中这是一个索引。否则 - never。所以,如果最后没有[number],你最终会得到[0, never]。通过[number] 对其进行索引返回0 | never,它基本上等于0。
我已经超载了GetType 以应用FindIndex。
另外,您可能已经注意到,为了推断字面量类型,您应该推断元素的每个属性。你应该从下往上走。
第一个通用 Type 推断 type 属性。然后,Elem 推断
数组的每个元素。最后Arr,感谢variadic tuple types 被完全推断出来。
您可以在我的博客here 和类型推断here 中找到有关元组操作的更多信息