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

调用联合返回类型函数时,条件运算符类型推断异常问题

TypeScript联合类型在条件/逻辑运算符中的类型推断问题

在TypeScript中,当通过条件运算符(三元)或逻辑运算符调用返回联合类型的函数时,会出现类型推断丢失部分联合成员的问题。比如以下代码中,thing、thing2、thing3、thing4的类型被推断为Row | "hi",但实际应该包含RowAndColumn:

type Row = { row: number };
type RowAndColumn = { row: number, column: number }

function getThing(input: number): RowAndColumn | Row | null {
    if (input < 0.3) return null;
    if (input < 0.5) return { row: 0 };
    return { row: 0, column: 0 };
}
const rand = Math.random();
const input = Math.random();

const thing = (rand > 0.5 && getThing(input)) || 'hi'; // 类型缺失RowAndColumn
const thing2 = (rand > 0.5 && getThing(input)) ?? 'hi'; // 类型缺失RowAndColumn
const thing3 = rand > 0.5 ? getThing(input) : 'hi'; // 类型缺失RowAndColumn
const thing4 = rand > 0.5 ? getThing(input) : getThing(input); // 类型缺失RowAndColumn

const correct = getThing(input); // 类型推断正确:RowAndColumn | Row | null
const correct2 = rand > 0.5 && getThing(input); // 类型推断正确:RowAndColumn | Row | null

问题原因

这是TypeScript的严格子类型收缩行为导致的:

  • RowAndColumn是Row的结构子类型,前者完全包含后者的所有属性。
  • 在逻辑运算符(&&/||/??)或三元运算符的类型计算中,TypeScript会自动将子类型合并到父类型中,只保留更宽泛的父类型(即Row),以此简化联合类型的复杂度。
  • 而直接调用函数或仅使用&&与函数返回值结合时,没有和其他异质类型(比如字符串"hi")进行联合,因此不会触发这种子类型合并,能保留完整的联合成员。

解决办法

如果需要保留完整的联合类型,有两种常见方案:

  1. 手动指定类型:显式声明变量的完整类型:
const thing: Row | RowAndColumn | "hi" = (rand > 0.5 && getThing(input)) || 'hi';
  1. 使用可区分联合:给类型添加唯一的区分标志,打破子父类型关系:
type Row = { type: 'row', row: number };
type RowAndColumn = { type: 'rowAndColumn', row: number, column: number }

function getThing(input: number): RowAndColumn | Row | null {
    if (input < 0.3) return null;
    if (input < 0.5) return { type: 'row', row: 0 };
    return { type: 'rowAndColumn', row: 0, column: 0 };
}

此时TypeScript会保留所有联合成员,不会进行子类型合并。

内容的提问来源于stack exchange,提问作者Jeremy Bernier

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 10:57:19