You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 07:06:17