Search code examples
typescriptreduxreact-reduxredux-thunkthunk

Typing dispatch on a redux store correctly when using multiple middleware


I'm attempting to configure the dispatch type on a redux store that is using thunk middleware and an optional middleware logger (redux-logger).

This correctly infers the thunk type on store's dispatch...

import { createStore, applyMiddleware } from 'redux';
import thunk, { ThunkMiddleware } from 'redux-thunk';

// ...

const preloadedState = undefined;
export const store = createStore(rootReducer, preloadedState, applyMiddleware(thunk as ThunkMiddleware));

enter image description here

When I expand the middleware to include a conditional logger and spread an array of middleware into applyMiddleware, the store's dispatch is not correctly inferred.


import { createStore, applyMiddleware, Middleware } from 'redux';
import thunk, { ThunkMiddleware } from 'redux-thunk';
import { createLogger } from 'redux-logger';

// ...

const middleware: Middleware[] = [thunk as ThunkMiddleware];

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));

enter image description here

This is driving me crazy, any thoughts as to how to fix the typing issue when spreading the middleware array?


Solution

  • This is where redux-toolkit comes in real handy.

    Their docs mention to do it this way

    import { configureStore } from '@reduxjs/toolkit'
    import { useDispatch } from 'react-redux'
    import rootReducer from './rootReducer'
    
    const store = configureStore({
      reducer: rootReducer,
    })
    
    export type AppDispatch = typeof store.dispatch
    export const useAppDispatch = () => useDispatch<AppDispatch>() // Export a hook that can be reused to resolve types
    
    export default store