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

TypeScript对联合类型推断出never类型的原因解析

问题解析:TypeScript类型收窄后推断为never的原因

你的代码里出现这个问题,核心在于**BarEntity的类型定义本质上和BaseEntity完全等价**,导致TypeScript对联合类型的收窄逻辑和你预期的不一样。

关键细节拆解

  1. 类型等价性
    你定义的BarEntity = BaseEntity & {},交叉一个空对象不会给原类型添加任何属性或约束,所以*BarEntity和BaseEntity*是完全相同的类型。

  2. 联合类型的简化
    Entity = FooEntity | BarEntity 实际上会被TypeScript简化为 FooEntity | BaseEntity。但因为*FooEntity是BaseEntity的子类型(它继承了BaseEntity的所有属性,还多了additionalData),所以整个联合类型最终会被进一步简化为BaseEntity*——因为任何FooEntity实例都符合BaseEntity的类型约束。

  3. 类型守卫的影响
    当你用isBarType(value)进行判断时,这个类型守卫断言value是*BarEntity(也就是BaseEntity)。由于Entity本质上就是BaseEntity,TypeScript会认为所有可能的Entity实例都满足isBarType的断言,所以在if分支之外,没有剩余的类型可以匹配,自然推断为never*。

为什么反向校验能生效?

当你用isFooType判断时,这个守卫明确区分了*FooEntity和其他BaseEntity实例。TypeScript能识别出:符合isFooType的是FooEntity,不符合的是普通BaseEntity(也就是你原本想表达的BarEntity*),所以收窄逻辑能正常工作。

修复方案

要让类型收窄符合你的预期,需要让*BarEntity和BaseEntity产生明确的类型差异,比如给BarEntity*添加一个独特的属性:

type BarEntity = BaseEntity & {
  type: 'bar'; // 添加区分属性
};

或者调整类型守卫的逻辑,直接针对*FooEntity*的特征进行判断:

function isFooType(value: Entity): value is FooEntity {
  return 'additionalData' in value;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 15:04:59