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

TypeScript可辨识联合在React reducer中报payload属性不存在错误

错误产生原因

你写的可辨识联合不满足TypeScript的类型缩窄要求,核心问题出在Action类型的定义上:

  • 可辨识联合的判别属性(这里是type字段)必须使用精确的字符串字面量类型,不能写宽泛的string。你现在两个联合分支的type字段类型都是string,TS根本没法通过action.type的具体值判断当前命中了哪个联合分支,自然做不了类型缩窄。
  • 两个联合分支的属性不统一:只有第一个分支声明了payload属性,第二个分支{ type: string }完全没有payload字段。TS在没法确定具体分支类型的时候,只允许访问所有分支共有的属性,payload不是公共属性,访问时就会抛出不存在的错误。
  • 额外提一句,你把带payload分支的payload类型写成AuthState也不合理,AuthState是整个认证状态的结构,登录成功动作的payload只需要返回用户信息和token就行,不需要完整的状态结构。
修复方案

把每个Action分支的type改成和case里对应的精确字符串字面量,同时明确每个动作对应的payload结构,不需要payload的分支就不要声明payload字段,修改后的代码如下:

// 定义登录成功动作携带的payload结构,也可以直接内联在类型定义里
type LoginSuccessPayload = {
  user: { id: string; name: string; email: string };
  access_token: string;
}

export type Action =
  | {
      type: "LOGIN_SUCCESS";
      payload: LoginSuccessPayload;
    }
  | { 
      type: "LOGOUT";
    };

改完之后TypeScript会在switch语句里自动根据action.type做类型缩窄:

  • 进入case "LOGIN_SUCCESS"分支时,TS会自动判定当前action是带payload的分支,可以安全访问action.payload.user、action.payload.access_token,不会再报类型错误
  • 进入case "LOGOUT"分支时,TS会判定当前action是无payload的分支,如果你误写了访问payload的代码还会主动提示错误
  • 原reducer里default分支抛错的逻辑可以保留,属于reducer编写的最佳实践,能拦截未定义的非法action。

内容的提问来源于stack exchange,提问作者B L Praveen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 23:51:25