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.