Search code examples
reactjstypescriptreduxredux-toolkit

How I set the correctly type for action.payload in redux-toolkit?


I am writing my first mern-stack with typescript. My login and register are working. Now I want to update, delete and get User via redux-toolkit. In the following code the whole lines from builder downwards to action.payload are underlined and I get the following error:

The AsyncThunkFulfilledActionCreator<object, object, AsyncThunkConfig> argument cannot be assigned to the string parameter.ts(2769)

I tried different things like saying object[] in the update function, tried it without the interface Initialstate. When I remove PayloadAction<User[]>, only action.payload is underlined and I get the error:

The object argument cannot be assigned to the WritableDraft parameter. Type {} is missing the following properties of type WritableDraft: firstname, lastname, username, email, and 8 others.ts(2345)

That is the code:

interface User{
  firstname:string
  lastname:string
  username:string
  email:string
  street:string
  number:string
  plz:string
  city:string
  password:string
  isAdmin:boolean
  createdAt: Date
  accessToken: string;
}
interface InitialState{
    user: User[],
    isLoading:boolean,
    isSuccess:boolean,
    isError:boolean,
    message:string,
}
const initialState:InitialState ={
    user: [],
    isLoading:false,
    isSuccess:false,
    isError:false,
    message:"",

}
type AsyncThunkConfig = {
    state: RootState
}
export const updateUser = createAsyncThunk<object, object, AsyncThunkConfig>('/user/update', async (updateData:object, thunkAPI)=>{
    try{
        const token = thunkAPI.getState().auth.user!.accessToken;
        return await userService.updateUser(updateData, token);
    }catch (error:any) {
      const message =
        (error.response &&
          error.response.data &&
          error.response.data.message) ||
        error.message ||
        error.toString()
      return thunkAPI.rejectWithValue(message as string)
    }
});
export const userSlice = createSlice({
    name: 'user',
    initialState,
    reducers:{
        reset:(state)=>{
            state.isLoading = false;
            state.isSuccess = false;
            state.isError = false;
            state.message = "";
        }
    },
    extraReducers(builder) {
      builder
      .addCase(updateUser.pending, (state)=>{
        state.isLoading = true;
      })
      .addCase(updateUser.fulfilled, (state, action:PayloadAction<User[]>)=>{
        state.isLoading = false;
        state.isSuccess = true;
        state.user.push(action.payload)
      })
    },
})

Solution

  • Assuming that userService.updateUser returns a User. You should type the Return argument as User

    export const updateUser = createAsyncThunk<User, object, AsyncThunkConfig>(
    

    You can then remove the type from the reducer, since addCase will automatically infer the types from your action.

          .addCase(updateUser.fulfilled, (state, action) => {
            state.isLoading = false;
            state.isSuccess = true;
            state.user.push(action.payload);
          });