TypeScript条件返回值相同但联合类型推断不一致问题求助
TypeScript函数条件返回值的联合类型推断一致性问题
以下两个逻辑完全一致的函数,TypeScript却推断出了不同的返回类型:
const register = (step: 1 | 2) => { if (step === 1) { return { otp: "", }; } return { userId: "", }; }; const register2 = (step: 1 | 2) => { if (step === 1) { const res = { otp: "", }; return res; } const res = { userId: "", }; return res; };
推断类型差异
register的返回类型:{ otp: string; userId?: undefined; } | { userId: string; otp?: undefined; }register2的返回类型:{ otp: string; } | { userId: string; }
使用时的问题
调用register(1)后可以直接访问user.otp进行判断:
const user = register(1); if (user.otp) { // 正常执行 } else { // 正常执行 }
但调用register2(1)时,直接访问user2.otp会报错:
const user2 = register2(1); if (user2.otp) { // 报错:Property 'otp' does not exist on type '{ otp: string; } | { userId: string; }' } else { // 报错 }
虽然可以用"otp" in user2的方式规避,但这种方式类型安全性不如直接访问属性(比如属性名重命名时容易出错)。需求是让register2自动推断出和register相同的返回类型,无需显式声明。
原因分析
TypeScript对直接返回对象字面量和先赋值给变量再返回的处理逻辑不同:
- 直接返回对象字面量时,TypeScript会启用严格字面量类型检查,自动为联合类型的每个成员添加缺失属性的
可选undefined声明,以此实现可辨识联合的类型收窄能力。 - 先将对象赋值给变量时,变量的类型会被自动拓宽为普通对象类型(比如
{ otp: string }),而不是保持字面量的严格类型,导致返回时无法触发联合类型的自动补全逻辑。
解决方案
在变量声明时使用as const来锁定对象的字面量类型,避免TypeScript拓宽类型:
const register2 = (step: 1 | 2) => { if (step === 1) { const res = { otp: "", } as const; return res; } const res = { userId: "", } as const; return res; };
此时register2的返回类型会自动推断为{ readonly otp: ""; userId?: undefined; } | { readonly userId: ""; otp?: undefined; },readonly修饰符不会影响属性的读取和判断逻辑,完全满足使用需求。
内容的提问来源于stack exchange,提问作者adityaa72
相关产品推荐
相关产品推荐

