Search code examples
typescriptaxios

axios TypeScript confusion - how to access response headers correctly?


How do I correctly use the axios-provided TypeScript types to handle errors and get response headers? In case of 429 (too many requests) my back-end sends a header "retry-after", that I would like to access. However, the elaborate types are driving me insane.

The following is what I got so far (example is a bit contrived because I simplified my actual code). I let IntelliJ specify some types explicitly.

This is giving an error on the headers.get(.. line:

TS2723: Cannot invoke an object which is possibly 'null' or 'undefined'.TS2723: Cannot invoke an object which is possibly 'null' or 'undefined'.

Huh? Where is null or undefined coming into play here? How do I do this correctly?

    axios
        .post<string>('api/refresh-token', credentials)
        .then(response => {
            const token = response.data;
            console.log("Token", token);
            // ...
        })
        .catch((error: Error | AxiosError) => {
            if (axios.isAxiosError(error)) {
                if(error.response) {
                    const response: AxiosResponse<unknown, any> = error.response;
                    const responseStatusCode: number = response.status;
                    if (responseStatusCode == 429) {
                        const headers: RawAxiosResponseHeaders | (RawAxiosResponseHeaders & AxiosHeaders) = response.headers;
                        const retryAfterText: any = headers.get("retry-after");
                    }
                }
            }
        });

Solution

  • headers.get is possibly null here.

    The Problem is the very broad definition of the headers variable's type.

    const headers: RawAxiosResponseHeaders | (RawAxiosResponseHeaders & AxiosHeaders) = response.headers;
    

    RawAxiosResponseHeaders is basically just a plain Object, a union that includes this interface:

    interface RawAxiosHeaders {
      [key: string]: AxiosHeaderValue;
    }
    

    And AxiosHeaderValue can be among a bunch of other things null.

    If you tell your IDE that you're expecting the AxiosHeaders type the get method will definitely not be null.

    You could check first if the Object is actually AxiosHeaders, then with the correct typing your code should work:

    if (responseStatusCode == 429) {
      const headers = response.headers;
      if (headers instanceof AxiosHeaders) {
        const retryAfterText = headers.get("retry-after");
      }
    }
    

    The retryAfterText variable will then have the type AxiosHeaderValue.