Redux+TypeScript中dispatch函数报类型不匹配错误如何解决
问题场景
在React+TypeScript技术栈使用原生Redux(非Redux Toolkit,仅用于学习)实现thunk风格的函数派发时,出现如下类型报错:
Argument of type '(dispatch: Dispatch) => void' is not assignable to parameter of type 'AnyAction'
相关业务代码:
- 函数1(postProducts):
const postProducts = (origin: string) => { return (dispatch: Dispatch) => { dispatch(initProducts(origin)) } }
- 函数2(initProducts):
export const initProducts = (origin: string) => { return (dispatch: Dispatch) => { if (origin !== 'load') { dispatch(setToastify(errorMsg)) } } }
- 函数3(setToastify):
export const setToastify = (toastifyDetails: string, open = true) => { return { type: ActionType.SET_TOASTIFY, toastify: toastifyDetails, open: open } }
报错根因
Redux默认导出的Dispatch类型仅支持派发带type字段的普通plain object action,不支持派发thunk风格的函数类型action。代码里的initProducts执行后返回值是一个函数,属于thunk action,用默认的Dispatch类型去约束dispatch方法时,TS会判定传入的函数类型不符合要求的AnyAction对象结构,直接抛类型错误。
另外要注意:原生Redux本身不支持派发函数,必须先注册redux-thunk中间件才具备这个运行时能力,类型修复是在运行时能力已经配置正确的前提下做的TS适配。
修复步骤
- 先确认运行时配置正确
安装redux-thunk依赖,在创建store时通过applyMiddleware注册thunk中间件,保证功能层面可以正常派发函数action。 - 替换默认的Dispatch类型为兼容thunk的类型
可以直接从store实例派生全局可用的正确类型,避免每次手动标注出错:
// store配置文件中 import { createStore, applyMiddleware, combineReducers } from 'redux'; import thunk from 'redux-thunk'; // 引入你自己的各个reducer // import productReducer from './xxx' // import toastReducer from './xxx' const rootReducer = combineReducers({ // products: productReducer, // toastify: toastReducer }) const store = createStore(rootReducer, applyMiddleware(thunk)) // 从store实例派生全局类型 export type RootState = ReturnType<typeof store.getState> // 这个AppDispatch会自动识别thunk中间件带来的类型扩展,同时支持普通对象action和函数action派发 export type AppDispatch = typeof store.dispatch
- 替换所有thunk函数里的dispatch类型标注
把原来写的dispatch: Dispatch全部换成dispatch: AppDispatch即可,修正后的代码示例:
// postProducts修正后 const postProducts = (origin: string) => { return (dispatch: AppDispatch) => { dispatch(initProducts(origin)) } } // initProducts修正后 export const initProducts = (origin: string) => { return (dispatch: AppDispatch) => { if (origin !== 'load') { dispatch(setToastify(errorMsg)) } } }
setToastify本身返回普通action对象,不需要做任何修改。
如果是在React组件里使用dispatch,推荐封装一个带类型的自定义hook,避免每次手动标注类型:
import { useDispatch } from 'react-redux' // 复用之前从store导出的AppDispatch类型 export const useAppDispatch = () => useDispatch<AppDispatch>()
组件里调用时直接用const dispatch = useAppDispatch()即可,不管派发普通action还是thunk函数都不会出现类型报错。
内容的提问来源于stack exchange,提问作者Berg_Durden
相关产品推荐
相关产品推荐

