Search code examples
typescriptmiddlewareredux-toolkitredux-saga

Type error Redux-Saga middleware with Typescript



I am trying to use redux-saga for side effects. As `createStore` is deprecated, I am trying to use `configureStore` from *@reduxjs/toolkit* (version 2.0.1). I followed different tutorials and found that there are two possibilities:
import { configureStore } from "@reduxjs/toolkit";
import createSagaMiddleware from "redux-saga";
import rootReducer from "./rootReducer";
import logger from 'redux-logger'
import { useDispatch } from 'react-redux'
import { rootSaga } from './rootSaga'

const sagaMiddleware = createSagaMiddleware();

const store = configureStore({
    rootReducer,
    middleware: (gDM) => gDM().concat(logger, sagaMiddleware)
  })

sagaMiddleware.run(rootSaga)

export type AppDispatch = typeof store.dispatch
export const useAppDispatch: () => AppDispatch = useDispatch

export default store;

that gives me this error:

Type '(gDM: GetDefaultMiddleware<any>) => Tuple<[ThunkMiddleware<any, UnknownAction, undefined>, Middleware<{}, any, Dispatch<AnyAction>>, SagaMiddleware<...>]>' is not assignable to type '(getDefaultMiddleware: GetDefaultMiddleware<any>) => Tuple<[ThunkMiddleware<any, UnknownAction, undefined>]>'.
  Type 'Tuple<[ThunkMiddleware<any, UnknownAction, undefined>, Middleware<{}, any, Dispatch<AnyAction>>, SagaMiddleware<object>]>' is not assignable to type 'Tuple<[ThunkMiddleware<any, UnknownAction, undefined>]>'.
    Type '[ThunkMiddleware<any, UnknownAction, undefined>, Middleware<{}, any, Dispatch<AnyAction>>, SagaMiddleware<object>]' is not assignable to type '[ThunkMiddleware<any, UnknownAction, undefined>]'.
      Source has 3 element(s) but target allows only 1

(if I remove the logger, the last line becomes Source has 2 element(s) but target allows only 1)

or

import { configureStore, Tuple } from "@reduxjs/toolkit";
import createSagaMiddleware from "redux-saga";
import rootReducer from "./rootReducer";
import logger from 'redux-logger'
import { useDispatch } from 'react-redux'
import { rootSaga } from './rootSaga'

const sagaMiddleware = createSagaMiddleware();

const store = configureStore({
    rootReducer,
    middleware: () => new Tuple(logger, sagaMiddleware)
  })

sagaMiddleware.run(rootSaga)

export type AppDispatch = typeof store.dispatch
export const useAppDispatch: () => AppDispatch = useDispatch

export default store;

that gives me this error:

Type '() => Tuple<[Middleware<{}, any, Dispatch<AnyAction>>, SagaMiddleware<object>]>' is not assignable to type '(getDefaultMiddleware: GetDefaultMiddleware<any>) => Tuple<[ThunkMiddleware<any, UnknownAction, undefined>]>'.
  Type 'Tuple<[Middleware<{}, any, Dispatch<AnyAction>>, SagaMiddleware<object>]>' is not assignable to type 'Tuple<[ThunkMiddleware<any, UnknownAction, undefined>]>'.
    Type '[Middleware<{}, any, Dispatch<AnyAction>>, SagaMiddleware<object>]' is not assignable to type '[ThunkMiddleware<any, UnknownAction, undefined>]'.
      Source has 2 element(s) but target allows only 1.

If I remove the logger, the error becomes:

Type '() => Tuple<[SagaMiddleware<object>]>' is not assignable to type '(getDefaultMiddleware: GetDefaultMiddleware<any>) => Tuple<[ThunkMiddleware<any, UnknownAction, undefined>]>'.
  Type 'Tuple<[SagaMiddleware<object>]>' is not assignable to type 'Tuple<[ThunkMiddleware<any, UnknownAction, undefined>]>'.
    Type '[SagaMiddleware<object>]' is not assignable to type '[ThunkMiddleware<any, UnknownAction, undefined>]'.
      Type 'SagaMiddleware<object>' is not assignable to type 'ThunkMiddleware<any, UnknownAction, undefined>'.
        Types of parameters 'next' and 'next' are incompatible.
          Type 'unknown' is not assignable to type 'T'.
            'T' could be instantiated with an arbitrary type which could be unrelated to 'unknown'

I am quite new to Typescript, and I am not understanding what is the problem...I searched online, but could not find anything useful.
Thank you in advance for your patience.


Solution

  • Check out this GitHub Issue, looks like it's the same issue with yours.

    Looks like there's been a type update since redux toolkit v2, which updates the redux middleware types from v4 to v5, causing middleware packages using v4 middlewares to be not compatible.

    I think you'll have to choose between two solutions.

    1. decide not to use redux toolkit v2, manually change its version to latest v1(I guess it is 1.9.7) in pacakage.json & run npm i
    2. override redux-logger, redux-saga 's redux version dependency to v5, as described in here

    One more thing : I think rootReducer must be given as a reducer property, and redux-logger middleware should be the last middleware

    Note: logger must be the last middleware in chain, otherwise it will log thunk and promise, not actual actions (ref)

    // ...
    const store = configureStore({
      reducer: rootReducer,
      middleware: (gDM) => gDM().concat(sagaMiddleware, logger)
    })
    // ...