TypeScript:如何根据属性值推断数组元素的索引
根据eventName自动推断TypeScript元组索引
基础类型定义
首先我们有以下TypeScript接口和数组类型:
// TypeScript接口 interface Event { eventName: string; eventShape: unknown; } // TypeScript数组类型 type Events = Event[];
已知用法:通过索引获取对应类型
我们可以通过指定元组的特定索引,直接获取对应位置的类型:
// 示例元组类型 type MyEventsType = [ { eventName: 'event1', eventShape: number, }, { eventName: 'event2', eventShape: string, }, ]; // 使用示例 const myFunction = <MyEvents extends MyEventsType>(myEvent: MyEvents[1]) => { myEvent.eventShape; // TypeScript能自动推断出这是string类型 };
需求:根据eventName值推断对应索引
现在需要实现的是:根据传入的eventName属性值,让TypeScript自动推断出它在元组中对应的索引。比如传入'event1'时得到索引0,传入'event2'时得到索引1。
我们已经有一个工具类型ExtractEventNames可以提取所有eventName的取值:
// 工具类型:提取所有eventName的值 type ExtractEventNames<T extends Events> = { [K in keyof T]: T[K] extends { eventName: infer Name } ? Name : never; };
实现方案:创建索引映射工具类型
我们可以新增一个工具类型GetEventIndex,实现eventName到元组索引的映射:
// 工具类型:根据eventName获取对应的元组索引 type GetEventIndex<T extends Events, E extends ExtractEventNames<T>[number]> = { [K in keyof T]: T[K]['eventName'] extends E ? K : never }[keyof T] extends infer I ? I extends number ? I : never : never;
使用示例
现在可以在函数中通过eventName自动推断出对应的索引,进而获取对应类型:
// 最终使用示例 const myFunction = <EventName extends ExtractEventNames<MyEventsType>[number]>(eventName: EventName) => { // 根据eventName推断出对应的元组索引 type EventIndex = GetEventIndex<MyEventsType, EventName>; // 获取对应索引的事件类型 const targetEvent = {} as MyEventsType[EventIndex]; targetEvent.eventShape; // 自动推断类型:传入'event1'时为number,传入'event2'时为string }; // 测试场景 myFunction('event1'); // targetEvent.eventShape类型为number myFunction('event2'); // targetEvent.eventShape类型为string
工具类型原理说明
GetEventIndex的逻辑是:
- 遍历元组的每个索引
K,判断该索引对应的eventName是否匹配目标值E - 匹配的索引保留为
K,不匹配的则设为never - 最后提取所有非
never的索引值,由于元组中每个eventName唯一,最终结果就是对应的数字索引
内容的提问来源于stack exchange,提问作者YAHsaves
相关产品推荐
相关产品推荐

