Redux-toolkit: wrong inferred type in createAsyncThunk

Created on 27 Aug 2020  路  7Comments  路  Source: reduxjs/redux-toolkit

Hi there,

I've defined my thunk as below.

const fetchUserById = createAsyncThunk(
  'users/fetchById',
  // Declare the type your function argument here:
  async (userId: number) => {
    const response = await fetch(`https://reqres.in/api/users/${userId}`)
    // Inferred return type: Promise<MyData>
    return (await response.json()) as MyData
  }
)

And when I try to use this thunk I'd expect to have autocomplete for the payload, but for some reason the payload has an inferred type of unknown.

    const { payload } = await dispatch(fetchUserById(3))

https://redux-toolkit.js.org/usage/usage-with-typescript#createasyncthunk

Most helpful comment

Yes, and I've already told you what the issue is :)

The base Dispatch type assumes that whatever is passed into dispatch() is what gets returned.

Middleware can return anything they want instead. In particular, the thunk middleware will return whatever your thunk function returns.

In order for TS to know about this, you have to tell it that you're using a version of the Dispatch type that has the thunk middleware typings included. The easiest way to do that is:

type AppDispatch = typeof store.dispatch;

and then you'd need to use that type here, inside your thunk, as the declared type of the dispatch argument. That way TS knows that this can return a promise.

But, the second issue is that createAsyncThunk is going to return _either_ the fulfilled action, _or_ the rejected action, as its result. So, you have to then check to see which one it is:

https://redux-toolkit.js.org/api/createAsyncThunk#handling-thunk-results

You can't just assume that it is the fulfilled action, which is what you're doing now.

All 7 comments

That's because:

  • You almost definitely haven't declared that you're using a type of dispatch that returns a promise
  • createAsyncThunk can return either the fulfilled action or the rejected action

See https://redux-toolkit.js.org/usage/usage-with-typescript#using-the-extracted-dispatch-type-with-react-redux

Sorry I'm a bit confused. Would you recommend the following way of ( in action creators ) using asyncActionCreator ?

export const checkForTaskSubmissionStatus = (payload: {
  taskSlug: TaskSlugEnum
}): AppThunk => async (dispatch, getState) => {
  try {
    const state = { ...getState() }
    const task = taskBySlugSelector(state, payload.taskSlug)
    const { organisation } = organisationSelector(state)

    const { payload: response } = await dispatch(
      getTaskSubmissionStatus({
        taskUUID: task!.uuid,
        organisationUUID: organisation?.uuid as string,
      })
    )

It looks fine syntactically, but the issue is that TS doesn't know that dispatch there can return a promise.

I _think_ you may be able to make it compile correctly by doing async (dispatch: MyThunkCapableDispatch) in there.

But, I'm also not sure how what you're showing there relates to the TS error you asked about originally.

@markerikson thanks for the help here. See the IDE is saying that response type is unknown

Screen Shot 2020-08-27 at 13 22 31

Yes, and I've already told you what the issue is :)

The base Dispatch type assumes that whatever is passed into dispatch() is what gets returned.

Middleware can return anything they want instead. In particular, the thunk middleware will return whatever your thunk function returns.

In order for TS to know about this, you have to tell it that you're using a version of the Dispatch type that has the thunk middleware typings included. The easiest way to do that is:

type AppDispatch = typeof store.dispatch;

and then you'd need to use that type here, inside your thunk, as the declared type of the dispatch argument. That way TS knows that this can return a promise.

But, the second issue is that createAsyncThunk is going to return _either_ the fulfilled action, _or_ the rejected action, as its result. So, you have to then check to see which one it is:

https://redux-toolkit.js.org/api/createAsyncThunk#handling-thunk-results

You can't just assume that it is the fulfilled action, which is what you're doing now.

something is not so right in the core of my application. Even after the changes I still get the unknown inferred

Screen Shot 2020-08-27 at 14 25 35

@sahanatroam The issues here really aren't a good place for us to provide support.

Since this is really a usage question, please ask this question over in Stack Overflow or Reactiflux where there are a lot more people ready to help you out.

Given that, I'm going to go ahead and close this.

Was this page helpful?
0 / 5 - 0 ratings