Reputation: 22670
In my Redux async thunks, I want to use the AppDispatch type that is inferred as described here: https://redux.js.org/recipes/usage-with-typescript
I followed the instructions here: https://redux.js.org/recipes/usage-with-typescript#typing-createasyncthunk
But when using this AppDispatch type in my custom ThunkApiConfig type (MyThunkApiConfig
in the following example), there will be a circular reference as demonstrated here: https://codesandbox.io/s/focused-joliot-ho45h?file=/src/usersSlice.ts:
'dispatch' is referenced directly or indirectly in its own type annotation.
Which makes sense, since there is a circular dependency between the dispatch type and the used thunks. But then how can I use AppDispatch in the async thunk?
Thanks for the answer in advance!
Upvotes: 2
Views: 2150
Reputation: 42228
There is no problem with using AppDispatch
in your MyThunkApiConfig
type. The problem comes about when you do that and also define your slice as a function of the async action. This causes a tight coupling between the slice types and the dispatch type which should not exist.
If the reducer is usersSlice.reducer
then there is no problem. This version uses the updateUser
aynsc thunk, which in turn uses the typed dispatch. But the type for the slice does not depend on the dispatch type. It is only concerned with the types for the state and the actions that it creates (in this case, none).
Your createAsyncSlice
on the other hand uses MyThunkApiConfig
in its argument type. So this creates a circle where the store type depends on the slice type and the slice type depends on the store type.
I fundamentally don't get what you are trying to achieve by passing the updateUser
aysnc thunk through a function instead of just using it directly. Obviously the easy solution here is "don't do that".
If you wanted to assign the type for AppDispatch
directly, you can of course do that. It's not recommended because the types are complex and rely on a lot of generic type parameters.
export type RootState = { users: UsersState }
export type AppDispatch = Dispatch<AnyAction> & ThunkDispatch<RootState, null, AnyAction>
In your example you don't actually need the MyThunkApiConfig
at all. You could just drop the generics from updateUser
. They will end up being inferred as <User, void, {}>
which is sufficient. You could type your slice argument as asyncThunk: AsyncThunk<User, void, {}>
and that would also fix the circular typings.
Upvotes: 3