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

Redux类型兼容疑问:添加类型联合后AnyAction可赋值给IAction2的原因

为什么AnyAction能赋值给IAction2却不能赋值给IAction?

哈哈,这个问题我写Redux + TypeScript的时候也踩过坑!咱们先把你没写完的代码补全(毕竟提到了ILoadUse...,应该是几个具体的Action类型),假设你的类型定义是这样的:

// 具体的Action类型
export interface ILoadUserBegin { type: "LOAD_USER_BEGIN"; }
export interface ILoadUserSuccess { type: "LOAD_USER_SUCCESS"; payload: User; }
export interface ILoadUserFail { type: "LOAD_USER_FAIL"; error: Error; }

// IAction是这些具体Action的联合类型
type IAction = ILoadUserBegin | ILoadUserSuccess | ILoadUserFail;

// IAction2是一个更宽泛的通用Action类型
interface IAction2 { type: string; }

再回忆Redux官方的AnyAction类型定义:

interface AnyAction {
  type: string;
  [extraProps: string]: any; // 允许任意额外属性
}

现在拆解两个赋值问题的核心:

1. 为什么AnyAction不能赋值给IAction?

这其实是TypeScript的字面量类型窄化和联合类型赋值规则在起作用:

  • IAction是几个具体字符串字面量type的联合类型,它的type只能是"LOAD_USER_BEGIN"、"LOAD_USER_SUCCESS"、"LOAD_USER_FAIL"这三个值之一——相当于TypeScript给它加了一个“只能是这几个值”的严格限制。
  • 而AnyAction的type是string类型,这是一个宽泛的“任意字符串”类型。TypeScript会较真:一个string类型的值有可能不是IAction联合里的那三个字面量(比如随便整个"UNKNOWN_ACTION")。
  • 为了保证类型安全,TypeScript绝对不会允许这种“可能不匹配”的赋值,所以AnyAction无法赋值给IAction。

2. 为什么AnyAction能赋值给IAction2?

这是TypeScript结构类型系统的核心规则在生效:

  • IAction2的定义只要求“有一个type属性,类型是string”,没有其他任何限制。
  • AnyAction完全满足这个结构:它的type是string类型,就算有额外属性,IAction2也不限制(如果IAction2带索引签名的话,AnyAction的索引签名也完全匹配)。
  • 在结构类型系统里,只要源类型的所有必填属性都能被目标类型覆盖,就允许赋值——所以AnyAction可以顺利赋值给IAction2。

你提到的“明明存在部分AnyAction无法赋值给IAction2”?

这里可能是你误解了:如果IAction2是{ type: string; }这种宽泛定义,那所有AnyAction的实例都符合它的结构,不存在无法赋值的情况。除非你的IAction2是带有其他必填属性的类型(比如{ type: string; payload: User; }),那确实有些AnyAction没有payload属性就无法赋值,但根据你的描述,显然IAction2是更宽松的通用类型。

总结一下:核心差异在于目标类型的具体程度——IAction是窄化的联合类型,要求type必须是特定字面量;IAction2是宽泛的通用类型,只要求type是string。AnyAction作为宽泛的“任意Action”类型,只能匹配同样宽泛的目标类型,无法匹配窄化的联合类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 07:59:00