TypeScript泛型问题:给定对象键时如何正确推断payload类型?
修复泛型EntityAction的类型推断问题
问题背景
原代码通过泛型EntityAction<T>定义实体更新的action类型,包含UPDATE_ENTITY(更新整个实体)和UPDATE_PROP(更新单个属性)两种分支。但当实体包含多个不同类型的属性时(如EntityA):
- 指定
propName: 'id'时,能正确提示缺少payload - 指定
propName: 'name'时,会出现payload类型不匹配的错误 - 移除
UPDATE_ENTITY分支后,类型推断恢复正常
问题根源
原EntityAction<T>的构造方式错误地将UPDATE_ENTITY分支嵌入到每个属性K的联合类型中,最终生成的类型会把所有UPDATE_PROP的propName与所有属性类型做无关联的合并,导致TypeScript无法正确关联propName和对应payload的类型。
修复方案
将UPDATE_ENTITY作为独立的联合分支,与所有属性对应的UPDATE_PROP分支分开定义,确保每个UPDATE_PROP的propName和payload保持严格的类型关联:
type EntityA = { name: string; id: number } type EntityB = { id: number; test1: number; test2: string; test3: number; test4: string; } // 修复后的EntityAction类型 type EntityAction<T> = // 单独定义UPDATE_ENTITY分支 { type: 'UPDATE_ENTITY'; payload: T; } // 为每个属性生成严格关联的UPDATE_PROP类型,再合并为联合 | { [K in keyof T]-?: { type: 'UPDATE_PROP'; propName: K; payload: T[K]; } }[keyof T]; function dispatch<T>(action: EntityAction<T>) { console.log(action); } // 验证用例 dispatch<EntityA>({ type: 'UPDATE_PROP', propName: 'id', payload: 123 }); // ✅ 类型匹配 dispatch<EntityA>({ type: 'UPDATE_PROP', propName: 'name', payload: 'test' }); // ✅ 类型匹配 dispatch<EntityA>({ type: 'UPDATE_PROP', propName: 'name', payload: 123 }); // ❌ 正确报错:number不能赋值给string dispatch<EntityA>({ type: 'UPDATE_ENTITY', payload: { id: 123, name: 'test' } }); // ✅ 类型匹配
修复原理
- 把
UPDATE_ENTITY从每个属性的分支中抽离,作为独立的联合成员,避免干扰属性与payload的类型关联 UPDATE_PROP部分仍通过映射类型为每个属性生成唯一的、propName与payload严格绑定的类型,再通过[keyof T]合并为联合类型,确保TypeScript能准确推断每个propName对应的payload类型
内容的提问来源于stack exchange,提问作者Cosmin Leferman
相关产品推荐
相关产品推荐

