如何为TypeScript联合类型创建对应类型的Payload映射对象?
问题
我想要创建一个payloads对象,让每个ActionType对应的属性值只能是该类型接口专属的Payload类型。以下是我尝试的代码,但当前写法无法实现预期效果:
enum ActionType { Add = 'add', Concat = 'concat' }; interface AddActionPayload { num1: number; num2: number; } interface ConcatActionPayload { str1: string; str2: string; } interface AddAction { type: ActionType.Add; payload: AddActionPayload; } interface ConcatAction { type: ActionType.Concat; payload: ConcatActionPayload; } type Actions = AddAction | ConcatAction; // 这里的写法会允许所有Payload类型混放,不符合需求 const payloads: Record<ActionType, Actions['payload']> = { add: { // 希望仅接受AddActionPayload类型 }, concat: { // 希望仅接受ConcatActionPayload类型 } }
解决方案
你需要使用映射类型结合条件类型,为每个ActionType精准提取对应的专属Payload类型。具体实现如下:
enum ActionType { Add = 'add', Concat = 'concat' }; interface AddActionPayload { num1: number; num2: number; } interface ConcatActionPayload { str1: string; str2: string; } interface AddAction { type: ActionType.Add; payload: AddActionPayload; } interface ConcatAction { type: ActionType.Concat; payload: ConcatActionPayload; } type Actions = AddAction | ConcatAction; // 定义映射类型,为每个ActionType匹配专属Payload type PayloadMap = { [T in ActionType]: Extract<Actions, { type: T }>['payload'] }; // 现在payloads的每个属性都会严格限制为对应ActionType的Payload类型 const payloads: PayloadMap = { add: { num1: 1, num2: 2 }, // 仅接受AddActionPayload,类型正确 concat: { str1: 'hello', str2: 'world' } // 仅接受ConcatActionPayload,类型正确 }; // 错误示例:如果给add传入ConcatActionPayload,TypeScript会报错 // const wrongPayloads: PayloadMap = { // add: { str1: 'a', str2: 'b' }, // 类型不匹配,编译错误 // concat: { num1: 3, num2: 4 } // 类型不匹配,编译错误 // };
原理说明
Extract<Actions, { type: T }>:从Actions联合类型中筛选出type属性等于当前T的成员(比如当T是ActionType.Add时,会筛选出AddAction)。- 随后通过
['payload']取出该成员的payload类型,最终PayloadMap会生成一个键为ActionType、值为对应专属Payload的类型。
这样就能确保payloads对象的每个属性只能接受对应ActionType的Payload类型,完全符合需求。
内容的提问来源于stack exchange,提问作者Uri Klar
相关产品推荐
相关产品推荐

