如何在TypeScript中声明键值匹配的对象区分类型
解决方案
这是个很典型的TypeScript类型细化需求,原来的Record<EventType, MyEvent[]>会让每个属性都接受所有MyEvent类型的元素,没法做到按键区分对应的值类型。我们可以通过映射类型+内置条件类型来实现精准的类型约束:
步骤1:定义提取对应事件类型的工具类型
首先我们需要一个工具类型,用来根据EventType枚举值,从MyEvent联合类型里筛选出对应的具体事件元组:
type ExtractEventByType<T extends EventType> = Extract<MyEvent, [T, ...any[]]>;
这里用到了TypeScript内置的Extract工具类型,它的作用是从联合类型中提取出符合指定条件的子类型。我们的条件是“元组的第一个元素等于目标EventType值”,通过[T, ...any[]]匹配任意以T开头的元组。
步骤2:生成精准的分组对象类型
接下来用映射类型遍历EventType的所有枚举值,为每个键生成对应的事件数组类型:
type EventsGrouped = { [K in EventType]: ExtractEventByType<K>[]; };
这个类型会为每个EventType枚举值K,生成一个值类型为ExtractEventByType<K>[]的属性——也就是只包含对应类型事件的数组。
步骤3:应用类型到对象
最后把eventsGrouped的类型替换成我们定义好的EventsGrouped:
enum EventType { A, B, C }; type MyEvent = [EventType.A, number] | [EventType.B, string] | [EventType.C, number, string]; type ExtractEventByType<T extends EventType> = Extract<MyEvent, [T, ...any[]]>; type EventsGrouped = { [K in EventType]: ExtractEventByType<K>[]; }; const eventsGrouped: EventsGrouped = { [EventType.A]: [], [EventType.B]: [], [EventType.C]: [], };
验证类型约束
现在你可以测试一下,TypeScript会严格约束每个数组的元素类型:
// ✅ 合法:EventType.A对应的事件类型是[EventType.A, number] eventsGrouped[EventType.A].push([EventType.A, 42]); // ❌ 非法:EventType.A的数组不能接受EventType.B的事件,会触发类型报错 eventsGrouped[EventType.A].push([EventType.B, "test"]); // ✅ 合法:EventType.C对应的事件类型是[EventType.C, number, string] eventsGrouped[EventType.C].push([EventType.C, 100, "hello"]);
内容的提问来源于stack exchange,提问作者forsen
相关产品推荐
相关产品推荐

