Redux dispatch动作时TypeScript报类型不存在属性的问题处理
问题根因
两处类型定义的硬编码,导致TypeScript无法正确串起dispatch调用到动作返回值的类型链路:
- 通用ThunkAction类型将返回值固定写死为
void。ReduxThunkAction的第一个泛型参数的作用就是定义thunk函数执行后的返回值类型,原本的定义把这个位置硬编码成void,不管实际thunk返回什么值,类型层面都会被标记为无有效返回值。 - 自带的dispatch类型没有做thunk适配。原生redux的dispatch默认只识别普通同步Action,不知道自己可以接收thunk函数、也不知道thunk函数执行后会有自定义返回值,自然无法把返回值类型同步给调用方。
之前尝试的手动类型断言失效,本质是因为动作本身的返回值类型已经被硬编码为“返回void的ThunkAction”,就算给dispatch传入目标返回值类型,也会因为传入的动作类型和dispatch的期望不匹配,导致泛型推导失效。
可直接生效的类型配置方案
1. 改造通用ThunkAction类型,预留返回值泛型入口
把原来硬编码void的ThunkAction定义改成带泛型参数的版本,保留默认值兼容原来无返回值的thunk写法:
import { Action } from "redux"; import { ThunkAction as ReduxThunkAction } from "redux-thunk"; import { IState } from "./store"; // 泛型参数TReturn默认值为void,适配无返回值的常规thunk type TThunkAction<TReturn = void> = ReduxThunkAction<TReturn, IState, unknown, Action<string>>;
2. 定义带返回值的动作时,通过泛型传入实际返回类型
针对有自定义返回值的action,把之前硬编码的TThunkAction替换成带实际返回值泛型的版本,动作本身的返回值类型会被正确关联:
export type TReturnValue = { someString: string }; // 传入TReturnValue作为ThunkAction的返回值泛型 export const someAction = (): TThunkAction<TReturnValue> => (dispatch) => { // thunk内部的返回值会被自动识别为TReturnValue return { someString: "some value" } };
3. 补全dispatch的类型定义,打通类型推导链路
在store定义的位置,把dispatch的类型扩展为支持thunk返回值的泛型函数,让TypeScript可以顺着动作的类型自动推导出返回值:
// store.ts 中导出扩展后的dispatch类型 type AppDispatch = <TReturn = void>( action: TThunkAction<TReturn> | Action<string> ) => TReturn;
调用效果
完成上述配置后,不需要任何手动类型断言,直接按常规方式调用dispatch,TypeScript就会正确识别返回值的属性:
// 无类型报错,someString会被正确识别为string类型 const { someString } = dispatch(someAction());
避坑提示
- 不要将所有thunk的返回值硬编码为void,ThunkAction的第一个泛型参数本身就是为自定义返回值预留的入口
- 不要跳过类型推导手动给dispatch传泛型,只要动作和dispatch的类型定义对齐,TypeScript会自动完成全链路的类型推导,手动传参反而容易因为两边类型不匹配失效
- 注意thunk内部的箭头函数写法:如果直接返回对象字面量,记得通过括号包裹对象或补充return关键字,避免JS语法歧义把大括号识别为函数体边界。
内容的提问来源于stack exchange,提问作者Mike K
相关产品推荐
相关产品推荐

