TypeScript中如何重命名联合类型中的字段?
解决TypeScript联合类型字段重命名问题
你的问题出在对联合类型使用Omit后交叉的方式上——Omit<Before, 'name'>返回的是Omit<A, 'name'> | Omit<B, 'name'>,再和{ name2: Before['name'] }交叉后,得到的是({ A: number } & { name2: 'A' | 'B' }) | ({ B: number } & { name2: 'A' | 'B' })。这种情况下,TypeScript无法确定你定义的对象属于哪个分支,严格检查时就会认为A字段可能不存在于另一个分支里,从而报错。
正确的做法是对联合类型的每个成员单独处理重命名,利用TypeScript的分布式条件类型来实现:
type A = { name: 'A' A: number } type B = { name: 'B' B: number } type Before = A | B // 定义通用的重命名工具类型 type RenameName<T> = T extends { name: infer N } ? Omit<T, 'name'> & { name2: N } : T; // 生成目标联合类型 type After = RenameName<Before> // 验证使用 const a: After = { name2: 'A', A: 2 }; // 无错误 const b: After = { name2: 'B', B: 3 }; // 无错误
原理说明
当T是联合类型时,分布式条件类型会自动将逻辑分发到联合的每个成员上。也就是说RenameName<Before>会被拆解为RenameName<A> | RenameName<B>:
- 对
A处理:移除name字段,添加name2: 'A',得到{ A: number; name2: 'A' } - 对
B处理:移除name字段,添加name2: 'B',得到{ B: number; name2: 'B' }
最终的After类型就是这两个处理后的类型组成的联合,完全符合你的需求,同时TypeScript能正确识别每个对象对应的分支,不会再出现属性不存在的错误。
内容的提问来源于stack exchange,提问作者kill129
相关产品推荐
相关产品推荐

