如何使用条件类型实现EventClientEvent的event与payload类型关联
解决TypeScript事件类型关联问题
要实现event字段和payload类型的严格绑定,最简洁的方案是使用可辨识联合类型(Discriminated Union),通过类型映射表关联事件名与对应payload类型,让TypeScript自动根据event的值推断payload的具体类型。
步骤1:定义事件-Payload类型映射表
先创建映射类型,把每个事件名和对应的payload类型(按需求包装为数组)绑定:
type TransactionRowTypes = { // transaction row types id: string; amount: number; }; type UserDataTypes = { // user data types userId: number; username: string; }; type InventoryRowTypes = { // inventory row types itemId: string; stock: number; }; // 核心映射表:事件名 → 对应payload类型 type EventPayloadMap = { transactions: TransactionRowTypes[]; userchange: UserDataTypes[]; inventory: InventoryRowTypes[]; };
步骤2:生成可辨识联合类型
基于映射表,将公共字段time与每个事件的专属字段合并,生成最终的EventClientEvent类型:
type EventClientEvent = { time: number; } & { // 遍历映射表所有键,生成每个事件的专属类型 [K in keyof EventPayloadMap]: { event: K; payload: EventPayloadMap[K]; }; }[keyof EventPayloadMap];
效果验证
使用该类型时,TypeScript会自动根据event的值推断payload类型:
function processEvent(event: EventClientEvent) { switch (event.event) { case 'transactions': // payload自动推断为TransactionRowTypes[] event.payload.forEach(tx => console.log(tx.amount)); break; case 'userchange': // payload自动推断为UserDataTypes[] console.log(event.payload[0].username); break; case 'inventory': // payload自动推断为InventoryRowTypes[] console.log(event.payload[0].stock); break; } }
关于你写的EventName类型
你定义的EventName<T>可用于提取单个事件类型的事件名字面量,但在当前方案中,直接从映射表提取所有事件名的联合类型更简洁:
// 等价于 'transactions' | 'userchange' | 'inventory' type EventName = keyof EventPayloadMap;
扩展性说明
后续新增事件时,只需在EventPayloadMap中添加新的键值对,EventClientEvent会自动包含新事件类型,无需修改其他代码。
内容的提问来源于stack exchange,提问作者thisjt
相关产品推荐
相关产品推荐

