使用多中间件时如何正确配置Redux Store的Dispatch类型
问题根因
你给middleware数组显式标注了通用的Middleware[]类型,直接擦除了ThunkMiddleware特有的类型信息,applyMiddleware无法基于丢失了类型特征的中间件数组,推断出支持Thunk异步调用的Dispatch类型。
修复方案
方案1:移除中间件数组的通用类型标注
不要给存放中间件的数组加Middleware[]类型约束,保留Thunk中间件的原生类型特征,同时显式定义全局的RootState和Dispatch类型供业务代码使用:
import { createStore, applyMiddleware } from 'redux'; import thunk, { ThunkMiddleware, ThunkAction } from 'redux-thunk'; import { createLogger } from 'redux-logger'; import rootReducer from './your-root-reducer-path'; // 全局RootState类型,后续useSelector等场景直接复用 export type RootState = ReturnType<typeof rootReducer>; // 全局Thunk Action类型,定义异步Action时复用 export type AppThunk<ReturnType = void> = ThunkAction< ReturnType, RootState, unknown, any >; // 移除Middleware[]类型标注,保留ThunkMiddleware的类型信息 const middleware = [thunk as ThunkMiddleware<RootState, any>]; if (Settings.environment === 'development') { const logger = createLogger({ collapsed: (_getState, _action, logEntry) => !logEntry.error }); middleware.push(logger); } const preloadedState = undefined; export const store = createStore(rootReducer, preloadedState, applyMiddleware(...middleware)); // 全局Dispatch类型,后续useDispatch等场景直接复用 export type AppDispatch = typeof store.dispatch;
方案2:显式指定applyMiddleware的类型参数
如果需要保留Middleware[]的数组类型标注,可以手动给applyMiddleware传入类型参数,直接锁定Thunk的类型特征,避免数组展开导致的类型丢失:
// 前面RootState、AppThunk等类型定义同上 const middleware: Middleware[] = [thunk as ThunkMiddleware<RootState, any>]; if (Settings.environment === 'development') { const logger = createLogger({ collapsed: (_getState, _action, logEntry) => !logEntry.error }); middleware.push(logger); } const preloadedState = undefined; export const store = createStore( rootReducer, preloadedState, // 显式传入类型参数,指定中间件为ThunkMiddleware,绑定RootState类型 applyMiddleware<ThunkMiddleware<RootState, any>, RootState>(...middleware) ); export type AppDispatch = typeof store.dispatch;
方案3(推荐):使用Redux Toolkit的configureStore
Redux官方目前推荐使用Redux Toolkit开发Redux应用,内置Thunk中间件,自动处理类型推断,添加自定义中间件的逻辑更简洁:
import { configureStore } from '@reduxjs/toolkit'; import { createLogger } from 'redux-logger'; import rootReducer from './your-root-reducer-path'; export type RootState = ReturnType<typeof store.getState>; export type AppDispatch = typeof store.dispatch; export const store = configureStore({ reducer: rootReducer, preloadedState: undefined, middleware: (getDefaultMiddleware) => { const baseMiddleware = getDefaultMiddleware(); // 开发环境插入logger if (Settings.environment === 'development') { const logger = createLogger({ collapsed: (_getState, _action, logEntry) => !logEntry.error }); return baseMiddleware.concat(logger); } return baseMiddleware; } });
内容的提问来源于stack exchange,提问作者Roy Kolak
相关产品推荐
相关产品推荐

