axios / axios

Promise based HTTP client for the browser and node.js
https://axios-http.com
MIT License
105.49k stars 10.92k forks source link

AxiosHeaders type is difficult to use #5967

Open selimb opened 1 year ago

selimb commented 1 year ago

Describe the bug

To Reproduce

https://codesandbox.io/s/axios-typescript-headers-issue-64vrrl?file=/src/index.ts

Code snippet

Copied from codesandbox above:

  const r = await axios.request({
    method: "get",
    url: "https://httpbin.org/response-headers",
  });

  // (1) TS ERROR: `.get` is not callable because `r.headers` may not be a `AxiosHeaders`
  r.headers.get("a");
  // Let's force it...
  // (2) TS ERROR: Nope, that doesn't work either.
  const headers = new AxiosHeaders(r.headers);

  if (!(typeof ha === "string" || Array.isArray(ha))) {
    // (3) TS ANNOYING: Narrows type of `ha` to `number | boolean | AxiosHeaders | null`
    //     In practice, only `undefined` is possible (AFAIK).
    ha;
  }

Expected behavior

Axios Version

1.5.1.4

Adapter Version

No response

Browser

N/A

Browser Version

N/A

Node.js Version

16.15.1

OS

N/A

Additional Library Versions

N/A

Additional context/Screenshots

N/A
selimb commented 1 year ago

I'd be happy to work on a PR.

Already have a proof-of-concept commit: https://github.com/selimb/axios/commit/58a5c71509c59b2acd2465cb5ba9aee29535fa88

Also just noticed docs for AxiosHeaders has recently been committed. Should probably update those as well.

kescherCode commented 10 months ago

Currently, to check within an interceptor whether a specific response header is contained within, one has to do this:

axiosInstance.interceptors.response.use((response) => {
    if (response.headers instanceof AxiosHeaders && response.headers.has('X-CSRF-Token')) {
        //...
    }

The instanceof check gets warned with Invalid 'instanceof' check: 'headers' has type that is not related to 'AxiosHeaders', but it is working nonetheless. Without this supposedly invalid instanceof check, it is impossible to do in TypeScript.