entropyfeverone
entropyfeverone

Reputation: 1572

How to use Axios interceptor with typescript correctly?

I have created an axios interceptor:

instance.interceptors.response.use(async (response) => {
    return response.data;
  }, (err) => {
    return Promise.reject(err);
  });

which gets the response and returns the data property.

The response object is of type AxiosResponse<any, any> and the data property is just the data of the type AxiosResponse<any, any>.data.

The problem is that when I use this axios client

const instance = axios.create({...});
// ...etc
// add interceptor

then I do:

customAxiosClient.get().then((data: /* here data is of type AxiosResponse instead of AxiosResponse.data */)

How to solve this ?

Upvotes: 6

Views: 20682

Answers (2)

Nicholas
Nicholas

Reputation: 2863

Answer by Rechu works, but I'm going to provide an alternative.

You can create a reusable function in order to keep your axios instance global. I use this myself in production.

First off, create a folder/file named utils/http.ts in your project. Next, this is my reusable function to keep everything in one place.

import axiosClient from "axios";
import type { AxiosRequestConfig } from "axios";

/**
 * Creates an initial 'axios' instance with custom settings.
 */
const instance = axiosClient.create({
  headers: {
    Accept: "application/json",
    "Content-Type": "application/json; charset=utf-8",
  },
});

/**
 * Handle all responses. It is possible to add handlers
 * for requests, but it is omitted here for brevity.
 */
instance.interceptors.response.use(
  (res) => res.data,
  (err) => {
    if (err.response) {
      return Promise.reject(err.response.data);
    }

    if (err.request) {
      return Promise.reject(err.request);
    }

    return Promise.reject(err.message);
  }
);

/**
 * Replaces main `axios` instance with the custom-one.
 *
 * @param cfg - Axios configuration object.
 * @returns A promise object of a response of the HTTP request with the 'data' object already
 * destructured.
 */
const axios = <T>(cfg: AxiosRequestConfig) => instance.request<any, T>(cfg);

export default axios;

Finally, use it like the following code snippet:

const login = () => {
  const creds = { username: "user", password: "pass" };

  axios<User>({ method: "POST", url: "/api/v1/auth/login", data: creds })
    .then((user) => { /* do whatever with user here */ })
    .catch((err) => { /* handle errors */);
};

It will be typed and ready for immediate usage. The any in axios function can be substituted with unknown as well.

Upvotes: 3

Rechu
Rechu

Reputation: 727

You have to just specify the response data type in axios get method, like so:

axios.get<never, YourDataType>(...)

Upvotes: 8

Related Questions