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

TypeScript中带公共属性的对象判别联合类型收窄后,直接访问属性为何无法通过泛型函数类型校验?

问题解答

这是个很典型的TypeScript类型收窄细节问题,我来给你拆解背后的原因:

核心原因:TypeScript对嵌套属性的类型跟踪局限性

首先,你通过action.payload.category !== Category.ROUTE_POINT的判断,确实已经把action.payload的类型收窄到了联合类型Payload中对应的分支——也就是{ category: Category.ROUTE_POINT; id: string; newValues: Partial<RoutePoint>; },这也是你悬浮查看action.payload.newValues时能看到正确类型的原因。

但问题出在回调函数的上下文里:当你在ArrayUtils.updateItemInArray的第三个参数(那个(p) => { ... }回调)中直接访问action.payload.newValues时,TypeScript的静态类型检查器没办法保证action.payload在回调执行时还是之前收窄后的类型。虽然在你的业务逻辑里action.payload肯定不会被修改,但TypeScript会做最保守的假设——它认为外部对象的属性可能在回调执行前被篡改,所以会把action.payload.newValues的类型退回到联合类型的原始状态:Partial<RoutePoint> | Partial<UnassignedRoutePoint>,这就和ArrayUtils.updateObject要求的Partial<RoutePoint>类型不匹配,导致报错。

为什么赋值给变量就生效?

当你把action.payload.newValues赋值给const newValues这个局部常量时,情况就不一样了:TypeScript会把这个常量的类型直接锁定为收窄后的Partial<RoutePoint>。因为newValues是局部的、不可修改的常量,TypeScript能确定它的类型在回调执行时不会发生变化,所以在回调里使用它时,类型校验自然就能通过。

额外小提示

如果你尝试把newValues改成let声明,可能会再次出现类型问题——因为let变量存在被修改的可能,TypeScript不会帮你锁定它的类型。所以这种场景下,用const声明局部变量是最稳妥的做法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 13:32:28