next-redux-wrapper: Store type mismatch when using redux-thunk

I want to use thunk’s AsyncAction from getInitialProps, but the type doesn’t match.

// --- In store module file
const fetch = ReduxToolkit.createAsyncThunk('count/fetch', async () => {
    // ... some codes
})

// --- In page file
const Page: Next.NextPage = () => {
    const count = useSelector(state => state.count)
    return <div>{count}</div>
}

Page.getInitialProps = async ({ store }) => {
    // TS2345: Argument of type 'AsyncThunkAction<Count, undefined, AsyncThunkConfig<unknown>>' is not assignable to parameter of type 'AnyAction'.   Property 'type' is missing in type 'AsyncThunkAction<Count, undefined, AsyncThunkConfig<unknown>>' but required in type 'AnyAction'.
    await store.dispatch(fetch())
    return {}
}

So this is how I wanted to solve it, but I couldn’t.

// --- In index.d.ts
port { NextPageContext } from 'next'
import { EnhancedStore } from '@reduxjs/toolkit'
import { ThunkMiddleware } from 'redux-thunk'

declare module 'next/dist/next-server/lib/utils' {
    export interface NextPageContext<S = any, A extends Action = AnyAction> {
        store: EnhancedStore<S, A, [ThunkMiddleware<S, A>]>
    }
}

I’m using redux-toolkit, but I think maybe even if someone is using pure thunk they’ll have the same problem. Please let me know if you have any other solutions.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 10
  • Comments: 23 (12 by maintainers)

Commits related to this issue

Most upvoted comments

While the issue isn’t fixed you can use the following workaround:

/* Export a dispatch type. */
export type AppThunkDispatch = ThunkDispatch<State, void, AnyAction>;
MyNextPage.getInitialProps = async ({ store }) => {
  /* Cast the store's dispatch function to the new type. */
  const dispatch = store.dispatch as AppThunkDispatch;
  await dispatch(someThunkAction());  // Now tslint doesn't complain anymore.
  return {};
};

P.S. Will be fixed in v7.0.

This part looks relevant: https://github.com/kirill-konshin/next-redux-wrapper/blob/3470c42b3219f038a02e5e241229face05c397c5/packages/wrapper/src/index.tsx#L22

From my understanding, the problem is that MakeStore is a function which returns a Store instead of something that extends Store, which is exactly the case with Redux Toolkit’s configureStore which returns an EnhancedStore:

export function configureStore<
  S = any,
  A extends Action = AnyAction,
  M extends Middlewares<S> = [ThunkMiddlewareFor<S>]
>(options: ConfigureStoreOptions<S, A, M>): EnhancedStore<S, A, M>
export interface EnhancedStore<
  S = any,
  A extends Action = AnyAction,
  M extends Middlewares<S> = Middlewares<S>
> extends Store<S, A>

(source)

I tried to play with the TypeScript declarations but wasn’t able to get it to work.

@kirill-konshin What do you think?

Thank you, I will look into it.

I am still not having enough time to fix this at the moment. If anyone can attempt to fix it w/o publishing a major release — you are most welcome…

I haven’t had time to look into this particular issue, sorry. It’s in the backlog, I will fix it as soon as I can. In the mean time you guys are most welcome to investigate it too.

@adonig you’re right, that’s the correct way, according to docs: https://redux-toolkit.js.org/usage/usage-with-typescript#getting-the-dispatch-type

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

Looks like even Redux Thunk itself does not have a cleaner way to tell store that it has modified the dispatch signature.

Closing.