TypeScript联合两种对象类型时无法正确推断类型的问题
解决TypeScript联合类型与Record类型的类型推断问题
问题分析
你定义的myType是{"204": {}}和Record<string, Record<string, number>>的联合类型,但在遍历Object.keys(param)时出现两个问题:
- 即使判断
code === "204",emptyRes的类型还是{} | Record<string, number>,无法精准缩小; - 非"204"分支报错,提示联合类型没有字符串索引签名。
核心原因:
Object.keys()返回的是string[]类型,而非字面量类型,TypeScript无法通过code === "204"直接缩小param的类型;- 联合类型中的
Record<string, ...>本身可以包含"204"键,所以仅判断键值无法区分两个联合成员。
解决方案:自定义类型保护函数
通过类型保护函数明确区分两个联合成员,再分别处理:
type myType = {"204": {}} | Record<string, Record<string, number>>; // 类型保护函数:判断是否是仅包含"204"键的对象 function is204Response(obj: myType): obj is {"204": {}} { return "204" in obj && Object.keys(obj).length === 1; } const foo = (param: myType) => { if (is204Response(param)) { // 这里param被缩小为{"204": {}}类型 const emptyRes = param["204"]; // 类型准确为{} } else { // 这里param被缩小为Record<string, Record<string, number>>类型 Object.keys(param).forEach(code => { const res = param[code]; // 类型准确为Record<string, number>,无报错 }); } };
补充说明
如果你的业务场景中,Record<string, Record<string, number>>类型不会包含"204"键,也可以简化类型保护逻辑:
function is204Response(obj: myType): obj is {"204": {}} { return typeof obj["204"] === "object" && Object.keys(obj["204"]).length === 0; }
关键是要让TypeScript明确当前param属于联合类型中的哪一个成员,才能实现精准的类型推断。
内容的提问来源于stack exchange,提问作者legends-killer
相关产品推荐
相关产品推荐

