createAsyncThunk redux toolkit with typescript rejecWithValue and Payload types error

Viewed 919

I'm trynig to implement authentifiaction slice in redux toolkit with typescript, but typescript is complaining about rejectWithValue error type and the action payload, please note that i'm using Axios and that i'm following the documentation but still complaining this my code


import { createAsyncThunk } from '@reduxjs/toolkit';
import { axiosClient } from 'src/network/api-client';
import {AxiosError} from 'axios'

type RegisterPayload = {
  login: string;
  password: string;
  client: string;
  first_name: string;
  last_name: string;
  patronymic: string;
  date_of_birth: string;
};
export type User = {
  token: string;
  refresh_token: string;
};
type KnownError = {
  errorMessage : string;
}
export const registerUser = createAsyncThunk<
{ token: string },
RegisterPayload,
{ rejectValue: KnownError }
>(
  'users/register',
  async (
    {
      login,
      password,
      client,
      first_name,
      last_name,
      patronymic,
      date_of_birth,
    }, // these are the lines that triggers the first error
    {rejectWithValue}
  ) => {
    try {
      const response = await axiosClient.post<User>('registration', {
        login,
        password,
        client,
        first_name,
        last_name,
        patronymic,
        date_of_birth,
      });
      if (response.status === 201) {
        localStorage.setItem('refresh', response.data.refresh_token);

        return {
          ...response,
          token: response.data.token,
        };
      }
    } catch (err) {
      const error: AxiosError<KnownError> = err;  // this os the lines 
                        that triggers the second error 'error' is underlined 
      if (!error.response) {
        throw err;
      }
      return rejectWithValue(error.response.data);
    }
);


and i'm having these errors

enter image description here

enter image description here

enter image description here

2 Answers

I had the same problem, I think the following method will solve your problem:

import axios, { AxiosResponse } from 'axios';
import { createAsyncThunk } from '@reduxjs/toolkit';

export interface CharacterSuccessResponse {
    info: Pagination,
    results: Character[]
}

export interface CharacterFailedResponse {
    error: string
}

export interface Character {
    id: number;
    name: string;
    status: string;
    species: string;
    type: string;
    gender: string;
    origin: Origin;
    location: Location;
    image: string;
    episode: string[];
    url: string;
    created: Date;
}

export interface Location {
    name: string;
    url: string;
}

export interface Origin {
    name: string;
    url: string;
}

export interface Pagination {
    count?: number;
    pages?: number;
    next?: string | null;
    prev?: string | null;
}

export const getCharactersAsync = createAsyncThunk<CharacterSuccessResponse, void, { rejectValue: CharacterFailedResponse }>('character/getCharactersAsync', async (_, thunkApi) => {
    try {
        const response = await axios.get('https://rickandmortyapi.com/api/characters')
        return response?.data
    } catch (error: any) {
        return thunkApi.rejectWithValue(error.response?.data)
    }
})

I hope this resource is useful

Regarding the first error, the first parameter of the async arrow function should be a RegisterPayload:

export const registerUser = createAsyncThunk<
  { token: string }, 
  RegisterPayload, 
  { rejectValue: KnownError }>
(
  'users/register',
  async (userData, {rejectWithValue}) => {...}
)

Where userData is for example:

userData = {
  login: 'my_login';
  password: 'my_password';
  client: '1234';
  first_name: 'John';
  last_name: 'Doe';
  patronymic: 'Johnson';
  date_of_birth: '1970-01-01';
}

For the second error, contrary to what the official documentation suggest, I use the type assertion of typescript described here: https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#type-assertions

catch (err) {
  const error = err as AxiosError<KnownError>; 
  if (!error.response) {
    throw err;
  }
  return rejectWithValue(error.response.data);
}
Related