TypeScript: correct typing for return type of AsyncThunk when using 'unwrapResult' of Redux Toolkit

Viewed 953

I'm struggling to find the right type for my return type of a AsyncThunkAction to use it with the unwrapResult method of Redux Toolkit (see: Redux Tookit: Unwrapping Result Actions):

Declaration of Async thunk in Slice:

export
 const createChannel = createAsyncThunk<
  { id: string },
  ChannelReqDto,
  InjectedAxiosClientType
>("channel/createChannel", async (req, thunkApi) => {
  const result = await thunkApi.extra.client.post(
    `/store/${req.storeId}/channels`,
    {
      category: req.category,
      group: req.group,
      name: req.name,
      rules: [],
    }
  );
  return result.data;
});

Usage in React Component:

const newChannel = await dispatch(
    createChannel({
        name: name,
        group: group,
        category: category,
        storeId: storeIdParam,
        rules: [],
    })
);
const result = unwrapResult(newChannel);

TypeScript Error:

TS2345: Argument of type 'AsyncThunkAction<{ id: string; }, ChannelReqDto, InjectedAxiosClientType>' is not assignable to parameter of type 'UnwrappableAction'.   Property 'payload' is missing in type 'AsyncThunkAction<{ id: string; }, ChannelReqDto, InjectedAxiosClientType>' but required in type 'UnwrappableAction'.

The result type needs to extend the interface UnwrappableAction but somehow I can't get it to work without ts-ignore:

export declare function unwrapResult<R extends UnwrappableAction>(action: R): UnwrappedActionPayload<R>;
1 Answers

@acemarke gave me the answer in the Reactiflux chat:

I had to use the typed dispatch ideally declared in the redux store (in my case store.tsx):

export type AppDispatch = typeof store.dispatch;
export const useAppDispatch = () => useDispatch<AppDispatch>();
  • store.dispatch(), by default, returns the action you passed in
  • middleware can modify the return value and swap for something else instead
  • the thunk middleware does that, by returning whatever your thunk function returns
  • the base Dispatch type doesn't know the thunk middleware is installed, so it thinks it'll return whatever you passed in - in this case, the thunk function itself
  • the thunk function is definitely not "unwrappable", nor does it have a payload field
  • switching to the customized AppDispatch type means that TS now recognizes that "the return type of dispatch is whatever this thunk function returns" instead
Related