Leveraging Axios interceptors in Typescript

How can I effectively utilize axios interceptors with TypeScript?

import axios, { AxiosRequestConfig, AxiosInstance } from 'axios'

HTTP.interceptors.request.use((config: AxiosRequestConfig) => config)

For instance, when creating an axios instance, default configuration is set up:

const conf: AxiosRequestConfig = {
  baseURL: process.env.VUE_APP_API_URL
}

const HTTP: AxiosInstance = axios.create(conf)

However, when attempting to use interceptors with customized headers:

HTTP.interceptors.request.use((config: AxiosRequestConfig) =>{
  headers: {
    'x-projectkey': 1234
  }
})

The above approach does not produce the desired outcome:

Argument of type '(config: AxiosRequestConfig) => void' is not assignable to parameter of type '(value: AxiosRequestConfig) => AxiosRequestConfig | Promise<AxiosRequestConfig>'

As a newcomer to TypeScript, this issue has me puzzled.

Answer №1

Looking at the definition of AxiosRequestConfig, it is clear that all parameters, including axios headers, are optional:

interface AxiosRequestConfig<D = any> {
  url?: string;
  method?: Method | string;
  baseURL?: string;
  timeout?: number;
  timeoutErrorMessage?: string;
  withCredentials?: boolean;
  // ... omitted 
}

When setting up an axiosInstance and configuring it, the returned config will be applied to the instance for proper configuration:

const axiosInstance = axios.create();

axiosInstance.interceptors.request.use((config) => {
  if (config.headers) { // <- checking for headers 
    config.headers["x-projectkey"] = 1234; // no errors
  }
  config.withCredentials = true; // to include credentials, this should be outside of the "if" block 
  return config;
});

Subsequently, every request made using the axiosInstance will automatically include the added x-projectkey header and credentials:

axiosInstance.get("url");

Answer №2

Here is an example configuration that you can use:

HTTP.interceptors.request.use((config: AxiosRequestConfig) => {
  config.headers['x-projectkey'] = 1234

  return config
})

Enjoy customizing your settings.

Answer №3

If you encounter the error mentioned, it is likely due to a missing return statement in your code. To resolve this issue, you can use the following approach:

HTTP.interceptors.request.use((config: AxiosRequestConfig) =>({
  headers: {
    'x-projectkey': 1234
  }
}))

Alternatively, you can include the return keyword as shown below:

HTTP.interceptors.request.use((config: AxiosRequestConfig) =>{
  return {
    headers: {
      'x-projectkey': 1234
    }
  }
})

Answer №4

Thank you for your recommendations. However, the issue I encountered was not related to that. I had already returned the config as required. The problem turned out to be much simpler than anticipated. I found the solution by setting the defaultReplyHeaders while creating a nock scope.

I also made changes to how the OPTIONS request was intercepted.

This is how it now works:

import { describe, expect, it } from '@jest/globals';
import nock from 'nock';
import type { Config } from './dependency-injection/config';
import type { ChooseApiRequest } from './api/contract/choose/ChooseApiRequest';
import type { Choice, ChooseApiResponse } from './api/contract/choose/ChooseApiResponse';
import { dy } from './services';

// Code continues here...

Answer №5

The issue lies in the fact that your code has a void return, as indicated by the error message. The snippet you provided is:

HTTP.interceptors.request.use((config: AxiosRequestConfig) =>{
  headers: {
    'x-projectkey': 1234
  }
})

The { following the => is being interpreted as the beginning of a function body. Therefore, you have a function with an invalid statement. As suggested by @miguelcg in their response on Stack Overflow, you should enclose the object in parentheses to directly return it or use return.

It's also advisable to set headers ON config instead of solely returning an object with your headers setting. Otherwise, you risk overriding any other configurations.

A recommended approach would be:

HTTP.interceptors.request.use((config: AxiosRequestConfig) => ({
  ...config,
  headers: {
    ...config.headers,
    'x-projectkey': 1234
  }
}))

This method preserves the rest of the configuration and does not replace any existing headers (unless that was the intention).

Alternatively, stick with the original structure and modify the code like this:

HTTP.interceptors.request.use((config: AxiosRequestConfig) => {
  if (config.headers) {
    config.headers['x-projectkey'] = 1234
  } else {
    config.headers = {
      'x-projectkey': 1234
    }
  }
  return config
})

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Testing NestJS Global ModulesExplore how to efficiently use NestJS global

Is it possible to seamlessly include all @Global modules into a TestModule without the need to manually import them like in the main application? Until now, I've had to remember to add each global module to the list of imports for my test: await Tes ...

Having trouble importing an object from another file in Typescript?

I'm facing a peculiar issue where I am unable to import a const declared in one file into another file. When trying to import the const, a TS error pops up stating Module '"../resources/dummy_container"' has no exported member &apo ...

Why is it possible in Angular Typescript to assign a Promise<ClassA> to an object of ClassA?

Recently, I started learning Angular and came across this snippet of code in my company's project: currentCDFlow: CDCurrentFlowDTO; this.currentCDFlow = await this.serivce.getCDMaster(); The code for getCDMaster() looks like this: public async get ...

Encountering type errors in NextJS with TypeScript

I am facing an issue while trying to run this function: "use server"; export const addProduct = async (formData: FormData, imageUrl: string) => { const productName = formData.get("productName")?.toString(); const description = f ...

Creating image paths for a list of items in reactjs can be achieved by mapping through the list

My goal is to display a list of items, with each item being assigned an image based on its ID: private static renderItemsTable(products: Product[]) { return <table className='table'> <thead> <tr> ...

How can Angular developers properly implement token refreshing in their applications?

Recently, I've been struggling with implementing a logic in my code. I have a specific requirement: Whenever there is a signed request (signed - means it has a JWT token for authenticated users) made to the API backend, the API backend may respond w ...

Solving the error message "Cannot find module '@angular/router/src/utils/collection' or its corresponding type declaration"

How do I troubleshoot this Error: src/app/metronic/orderByLocation/locationsByOneOrder/locationsByOneOrder.component.ts:7:25 - error TS2307: Cannot find module '@angular/router/src/utils/collection' or its corresponding type declarations.m 7 imp ...

What is the best approach to creating a Typescript library that offers maximal compatibility for a wide range

My Vision I am aiming to develop a versatile library that can cater to both JavaScript and TypeScript developers for frontend applications, excluding Node.js. This means allowing JavaScript developers to utilize the library as inline script using <scri ...

Error: The code is unable to access the '0' property of an undefined variable, but it is functioning properly

I am working with two arrays in my code: bookingHistory: Booking[] = []; currentBookings: any[] = []; Both arrays are populated later in the code. The bookingHistory array consists of instances of Booking, while currentBookings contains arrays of Booking ...

Utilize a Typescript library within a separate Typescript library

I have a TypeScript library on GitHub that I want to install using npm install --save git+ssh://<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="5f38362b1d15c3f4">[email protected]</a>:User/mylib.git into my targ ...

What is the process for setting the active state for HtmlBodyElement?

I attempted to use the following method: document.querySelector('body').setActive(); However, I encountered an error: TS2339: Property 'setActive' does not exist on type 'HTMLBodyElement'. Any suggestions on how to resolve t ...

selective ancestor label Angular 8

I am looking for a way to place my content within a different tag based on a specific condition. For instance, I need my content to be enclosed in either a <table> or <div> depending on the condition. <table|div class="someClass" ...

The specified function is not recognized within the HTMLButtonElement's onclick event in Angular 4

Recently diving into Angular and facing a perplexing issue: "openClose is not defined at HTMLButtonElement.onclick (index:13)" Even after scouring through various resources, the error seems to be rooted in the index page rather than within any of the app ...

When a URL is triggered via a browser notification in Angular 2, the target component ceases to function properly

Whenever I access a URL by clicking on a browser notification, the functionality of the page seems to stop working. To demonstrate this issue, I have a small project available here: https://github.com/bdwbdv/quickstart Expected behavior: after starting t ...

How can I execute a TypeScript / TSX file from a Next.js project in the terminal using ts-node?

One of my go-to tools is ts-node for running individual files. I'm currently attempting to execute files like ts-node ./page/home.tsx, but I'm encountering issues within my Next.js project. export const WidgetList = createWidget<ButtonListPro ...

Using Svelte with Vite: Unable to import the Writable<T> interface for writable store in TypeScript

Within a Svelte project that was scaffolded using Vite, I am attempting to create a Svelte store in Typescript. However, I am encountering difficulties when trying to import the Writable<T> interface as shown in the code snippet below: import { Writa ...

React encountering a 400 Bad Request Error with Axios

I've gone through all the posts about Axios 400 bad request, but I still can't find a solution. In my useEffect function, I first fetch data from my API and later on, depending on certain conditions, I may need to make a POST request back to the ...

Is it possible to spread an empty array in JavaScript?

Whenever I run the code below, I encounter the error message Uncaught SyntaxError: expected expression, got '...': [1,2,3, (true ? 4 : ...[])] I'm wondering if spreading an empty array in that manner is allowed? ...

Having difficulty storing duplicate requests that are crucial for various services/components

Currently, I am tackling a project that involves displaying multiple sets of data to the user. Each set requires several requests to be made to the backend. Specifically, for the UserDetails dataset, I must query the getUser and getSigns endpoints. However ...

Converting a string into a Date in Typescript while disregarding the timezone

Upon receiving a date in string format like this (e.g.): "11/10/2015 10:00:00" It's important to note that this is in UTC time. However, when creating a Date object from this string, it defaults to local time: let time = "11/10/2015 10:00:00"; let ...