Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeScript error when axios instance is created from an import that uses axios >=1.6.0's ESM types #400

Open
evelynhathaway opened this issue Oct 10, 2024 · 4 comments

Comments

@evelynhathaway
Copy link

Overview

With [email protected], [email protected], [email protected], using MockAdapter causes TypeScript to error about type differences between axios when imported via our ESM code and the types imported by axios-mock-adapter.

The newest axios version that this does not occur is [email protected], the type change seems to be introduced in [email protected]. However, I don't believe it's an axios issue, or at least one that's as straightforward as you may expect. axios's types ESM and CJS are composed of the same literals and unions for AxiosRequestHeaders, so I feel like TypeScript is providing an unhelpful error about assignability of members of what is functionally the same union. The crux is that the classes AxiosHeaders (ESM) and axios.AxiosHeaders (CJS) are not assignable.

Besides downgrading to [email protected], this also doesn't occur when using .cts or "type": "script". Unfortunately downgrading to a vulnerable axios version and rewriting our modules to CommonJS are not feasible workarounds for my team, so we're as any'ing the errors away.

Possible Fix

It appears that axios-retry fixed this assignability issue occurring from the different type files by using ESM or CJS axios types based on whether axios-retry was imported from ESM or CJS: softonic/axios-retry#159 (comment). Perhaps this approach would work for axios-mock-adapter?

CodeSandbox

https://codesandbox.io/p/devbox/yxnj2p?file=%2Fsrc%2Findex.ts%3A6%2C1

Error

Argument of type 'import("/project/workspace/node_modules/axios/index", { with: { "resolution-mode": "import" } }).AxiosInstance' is not assignable to parameter of type 'import("/project/workspace/node_modules/axios/index").AxiosInstance'.
  Types of property 'defaults' are incompatible.
    Type 'Omit<import("/project/workspace/node_modules/axios/index", { with: { "resolution-mode": "import" } }).AxiosDefaults<any>, "headers"> & { headers: import("/project/workspace/node_modules/axios/index", { with: { "resolution-mode": "import" } }).HeadersDefaults & { ...; }; }' is not assignable to type 'Omit<import("/project/workspace/node_modules/axios/index").AxiosDefaults<any>, "headers"> & { headers: import("/project/workspace/node_modules/axios/index").HeadersDefaults & { ...; }; }' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.
      Type 'Omit<AxiosDefaults<any>, "headers"> & { headers: HeadersDefaults & { [key: string]: AxiosHeaderValue; }; }' is not assignable to type 'Omit<AxiosDefaults<any>, "headers">' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.
        Types of property 'transformRequest' are incompatible.
          Type 'import("/project/workspace/node_modules/axios/index", { with: { "resolution-mode": "import" } }).AxiosRequestTransformer | import("/project/workspace/node_modules/axios/index", { with: { "resolution-mode": "import" } }).AxiosRequestTransformer[]' is not assignable to type 'import("/project/workspace/node_modules/axios/index").AxiosRequestTransformer | import("/project/workspace/node_modules/axios/index").AxiosRequestTransformer[]'.
            Type 'AxiosRequestTransformer' is not assignable to type 'AxiosRequestTransformer | AxiosRequestTransformer[]'.
              Type 'import("/project/workspace/node_modules/axios/index", { with: { "resolution-mode": "import" } }).AxiosRequestTransformer' is not assignable to type 'import("/project/workspace/node_modules/axios/index").AxiosRequestTransformer'.
                The 'this' types of each signature are incompatible.
                  Type 'import("/project/workspace/node_modules/axios/index").InternalAxiosRequestConfig<any>' is not assignable to type 'import("/project/workspace/node_modules/axios/index", { with: { "resolution-mode": "import" } }).InternalAxiosRequestConfig<any>' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.
                    Types of property 'headers' are incompatible.
                      Type 'import("/project/workspace/node_modules/axios/index").AxiosRequestHeaders' is not assignable to type 'import("/project/workspace/node_modules/axios/index", { with: { "resolution-mode": "import" } }).AxiosRequestHeaders' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.
                        Type 'AxiosRequestHeaders' is not assignable to type 'Partial<RawAxiosHeaders & { Accept: AxiosHeaderValue; "Content-Length": AxiosHeaderValue; "User-Agent": AxiosHeaderValue; "Content-Encoding": AxiosHeaderValue; Authorization: AxiosHeaderValue; } & { ...; }>' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.
                          Types of property 'Accept' are incompatible.
                            Type 'import("/project/workspace/node_modules/axios/index").AxiosHeaderValue' is not assignable to type 'import("/project/workspace/node_modules/axios/index", { with: { "resolution-mode": "import" } }).AxiosHeaderValue'.
                              Type 'AxiosHeaders' is not assignable to type 'AxiosHeaderValue'.
                                Type 'AxiosHeaders' is missing the following properties from type 'string[]': length, pop, push, join, and 33 more.

Minimal TypeScript Code Triggering Error

import axios from "axios";
import MockAdapter from "axios-mock-adapter";

export const axiosInstance = axios.create({});
new MockAdapter(axiosInstance);

TypeScript Config

{
	"compilerOptions": {
		"lib": [
			"esnext",
			"dom"
		],
		"target": "ES2022",
		"module": "Node16",
		"moduleResolution": "Node16",
		"strict": true,
		"noFallthroughCasesInSwitch": true,
		"exactOptionalPropertyTypes": true,
		"forceConsistentCasingInFileNames": true,
		"esModuleInterop": true
	}
}
@evelynhathaway
Copy link
Author

@remcohaszing I saw you were an author on axios's ESM types and you fixed #371. You seem knowledgeable about this area, and I hope you don't mind the ping. ❤️

@remcohaszing
Copy link
Contributor

I think axios/axios#6218 would resolve the issue.

@yourinium
Copy link

Any chance there is some sort of workaround to make this work until this is merged in?

@danitt
Copy link

danitt commented Nov 25, 2024

Any chance there is some sort of workaround to make this work until this is merged in?

@yourinium as @evelynhathaway said a dirty "any" cast will keep it compiling until we have a proper fix, e.g.

// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument
    axiosMock = new MockAdapter(axios as any);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants