From the docs, I can get the type of dispatch by using typeof store.dispatch, this works well with the default middlewares. However, when I add my custom middleware, the inferred type of dispatch becomes Dispatch<AnyAction>. My question is, how can I properly type the custom middleware to make everything work together?
Here is the code for my store set up:
import { configureStore, getDefaultMiddleware, Action } from '@reduxjs/toolkit';
import { ThunkAction } from 'redux-thunk';
import { createLogger } from 'redux-logger';
import rootReducer, { RootState } from './rootReducer';
const middleware = [...getDefaultMiddleware<RootState>()];
if (process.env.NODE_ENV === 'development') {
middleware.push(createLogger());
}
function configStore(initialState: any) {
const store = configureStore({
reducer: rootReducer,
middleware,
preloadedState: initialState,
});
if (process.env.NODE_ENV === 'development' && module.hot) {
module.hot.accept('./rootReducer', () => {
const newRootReducer = require('./rootReducer').default;
store.replaceReducer(newRootReducer);
});
}
return store;
}
export type AppDispatch = ReturnType<typeof configStore>['dispatch'];
export type AppThunk = ThunkAction<void, RootState, unknown, Action<string>>;
export default configStore;
with this setup, the inferred type of dispatch is

when I add my custom middleware, I just change
const middleware = [...getDefaultMiddleware<RootState>()];
to
const middleware = [...getDefaultMiddleware<RootState>(), customMiddleware];
then the inferred dispatch becomes

This will cause ts to complain when I dispatch a thunk action

Here is how I define my custom middleware
const customMiddleware: Middleware<{}, RootState> = store => next => action => {
console.log(store.getState());
const res = next(action);
console.log(res);
return res;
};
I have tried the suggestions in the doc but it does not solve the problem. https://redux-toolkit.js.org/usage/usage-with-typescript/#correct-typings-for-the-dispatch-type
Could someone help me?
note: I'm using version 1.2.4
This seems to be a problem with TS losing some of the types in the middleware array, making it a Middleware[] type. :/
Does it help if you define it in this order?
const middleware = [customMiddleware, ...getDefaultMiddleware<RootState>()] as const;
@phryneas nope, as long as I add a custom middleware, the middleware array types change from

to

For me it seemed to be to be working in https://codesandbox.io/s/elegant-water-zyyvh , but now after a reload it isn't :/
This type erasure is deeply unsatisfying and I'm a bit out of ideas right now :(
Could you maybe ask a TS question on StackOverflow how one would best preserve all array value types here and report back?
There are some real type wizards over there, maybe one of them has a better idea.
@phryneas Thanks for the feedback. For sure I can post a question on StackOverflow but I'm not sure I can describe the problem properly since I'm just new to typescript.
I could do so too, but at the earliest 10 hours from now. I'd say just give it a try, the wizards over there are pretty good to figure out the intentions of the question ^^
Make sure to mention that it's an unintended type information erasure or something like that ^^
I found that this issue caused by the order of custom middlewares.
for example,

this works fine (...defaultMiddleware should be the last order)

but this doesn't work
If you have to change the order of middlewares, you should annotate the middlewares type manually. For example,
const middleware: Array<Middleware<{}, AppState> | ThunkMiddleware<AppState, AnyAction, { axios: AxiosInstance }>> = [
...defaultMiddleware,
ReduxNotifier,
setUserToTracker,
loggerMiddleware,
];
Most helpful comment
If you have to change the order of middlewares, you should annotate the middlewares type manually. For example,