Typescript如何为处理异步action的自定义Redux中间件标注类型
问题根因
你遇到的类型报错核心原因是:你定义的中间件将最后一层的入参限制为AnyAction类型(要求必须携带type字段),但createAsyncThunk生成的AsyncThunkAction本质是一个函数,不属于标准AnyAction范畴,因此和中间件定义的入参类型冲突。
解决方案
调整中间件的入参类型定义,兼容所有可被dispatch的内容,仅对符合条件的标准Action做错误捕获逻辑,其他内容直接透传给下游中间件处理即可,修改后的代码如下:
import { Middleware, MiddlewareAPI, Dispatch, isAction } from '@reduxjs/toolkit'; // 自定义Action的meta字段类型 interface ICustomActionMeta { withErrorHandler?: boolean; defaultErrorCode?: number; // 补充其他你用到的meta字段 } // 定义需要处理的Action类型约束 interface IProcessableAction extends Action { payload?: unknown; meta: ICustomActionMeta; } // 类型守卫:判断是否为需要处理的标准Action const isProcessableAction = (action: unknown): action is IProcessableAction => { return isAction(action) && 'meta' in action; }; // 判断是否为Promise的工具函数 const getIsPromise = (val: unknown): val is Promise<unknown> => { return typeof val === 'object' && val !== null && 'then' in val && 'catch' in val; }; // 改造后的错误捕获中间件 const errorMiddleware: Middleware = ({ dispatch }: MiddlewareAPI) => (next: Dispatch) => async (action: unknown) => { if (isProcessableAction(action)) { const { meta, payload } = action; const { withErrorHandler, defaultErrorCode } = meta; if (getIsPromise(payload) && withErrorHandler) { return next(action) .catch(errorHandler(defaultErrorCode)) .catch((handledError: ISystemError) => Promise.reject( handledError.shouldSkipHandleError ? handledError : dispatch(addError(handledError)) ) ); } } // 非标准Action(包括AsyncThunkAction等函数类型)直接透传 return next(action); };
注意事项
如果需要捕获createAsyncThunk执行后的Promise错误,需要注意中间件的注册顺序,要将错误中间件放在thunk中间件前面,使用RTK的configureStore时推荐写法如下:
const store = configureStore({ reducer: rootReducer, middleware: (getDefaultMiddleware) => getDefaultMiddleware() // 将错误中间件放在默认中间件(内置thunk)的最前面 .prepend(errorMiddleware) });
内容的提问来源于stack exchange,提问作者Wagner Moreira
相关产品推荐
相关产品推荐

