redux-toolkit icon indicating copy to clipboard operation
redux-toolkit copied to clipboard

Extended interface throws an immer type error

Open AlanJereb opened this issue 2 years ago • 1 comments

Hey everyone,

I have updated "react-redux" from v6 to v8, and I'm having trouble with immer types.

My asyncThunk

interface IGetLinkQuestions {
  linkId: string,
  pageNumber: number,
}
export const getLinkQuestions = createAsyncThunk<
  IQuestion[],
  IGetLinkQuestions,
  { rejectValue: ValidationErrors}
>(
  'data/getLinkQuestions',
  async (data: IGetLinkQuestions, { rejectWithValue }) => {
    const { linkId, pageNumber} = data;
    return await axios.post<IQuestion[]>("/data/getLinkQuestions", { linkId, pageNumber}, {withCredentials: true })
      .then((res) => {
          return res.data;
      })
      .catch((err) => {
        const error: AxiosError<ValidationErrors> = err // cast error for access
        if (!error.response) {
          throw err
        }
        return rejectWithValue(error.response?.data);
      });
  }
)

Builder with type error

    builder.addCase(getLinkQuestions.fulfilled, (state, action) => {
      if (action.payload.length) {
        for (const el of action.payload) {
          if (!state.links.displayedLinkQuestions.find((x) => x._id === el._id)) {
            state.links.displayedLinkQuestions.push(el);
          }
        }
      }
    });

The error occurs with el of type IQuestion that is being pushed in displayedLinkQuestions of type IQuestion[] image

The IQuestion interface, which is being used both for el and displayedLinkQuestions extends mongoose.Document. If I remove that extension, the errors go away. I, however, need it.

The code worked fine in v6.

AlanJereb avatar Oct 13 '22 20:10 AlanJereb

This has nothing to do with react-redux at all, as that has no dependency on immer whatsoever. It could be caused by a parallel immer update, so you would have to take that up to the immer repository.

You could manually declare the state type like

    builder.addCase(getLinkQuestions.fulfilled, (state : WhateverYourStateTypeIs, action) => {
      if (action.payload.length) {
        for (const el of action.payload) {
          if (!state.links.displayedLinkQuestions.find((x) => x._id === el._id)) {
            state.links.displayedLinkQuestions.push(el);
          }
        }
      }
    });

and that might probably solve the problem.

But generally, your schema there is probably just a "too complicated" type to map over. That happens e.g. with circular types and can probably not really be solved.

phryneas avatar Oct 13 '22 20:10 phryneas