openapistack / openapi-client-axios

JavaScript client library for consuming OpenAPI-enabled APIs with axios
https://openapistack.co
MIT License
558 stars 67 forks source link

type AxiosRequestConfig is not compatible with the one provided directly by axios. #48

Closed mat813 closed 3 years ago

mat813 commented 3 years ago

I am converting some code base to typescript, and I scratched my head for something like half an hour with this error:

TS2345: Argument of type '(config: AxiosRequestConfig) => AxiosRequestConfig' is not assignable to parameter of type '(value: AxiosRequestConfig) => AxiosRequestConfig | Promise<AxiosRequestConfig>'.
  Types of parameters 'config' and 'value' are incompatible.
    Type 'import("/home/mat/work/api-sig-elig/admin/node_modules/openapi-client-axios/node_modules/axios/index").AxiosRequestConfig' is not assignable to type 'import("/home/mat/work/api-sig-elig/admin/node_modules/axios/index").AxiosRequestConfig'.
      Types of property 'adapter' are incompatible.
        Type 'import("/home/mat/work/api-sig-elig/admin/node_modules/openapi-client-axios/node_modules/axios/index").AxiosAdapter | undefined' is not assignable to type 'import("/home/mat/work/api-sig-elig/admin/node_modules/axios/index").AxiosAdapter | undefined'.
          Type 'import("/home/mat/work/api-sig-elig/admin/node_modules/openapi-client-axios/node_modules/axios/index").AxiosAdapter' is not assignable to type 'import("/home/mat/work/api-sig-elig/admin/node_modules/axios/index").AxiosAdapter'.
            Types of parameters 'config' and 'config' are incompatible.
              Type 'import("/home/mat/work/api-sig-elig/admin/node_modules/axios/index").AxiosRequestConfig' is not assignable to type 'import("/home/mat/work/api-sig-elig/admin/node_modules/openapi-client-axios/node_modules/axios/index").AxiosRequestConfig'.
                Types of property 'validateStatus' are incompatible.
                  Type '((status: number) => boolean) | null | undefined' is not assignable to type '((status: number) => boolean | null) | undefined'.
                    Type 'null' is not assignable to type '((status: number) => boolean | null) | undefined'.
    29 | 
    30 |     client.interceptors.request.use(
  > 31 |       (config: AxiosRequestConfig): AxiosRequestConfig => {
       |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    32 |         const token = JSON.parse(localStorage.getItem('token') ?? 'null');
    33 | 
    34 |         if (token) {

All that because VSCode added the import from axios and not from openapi-client-axios. Then I noticed that difference:

❯ diff -u node_modules/axios/index.d.ts node_modules/openapi-client-axios/node_modules/axios/index.d.ts
--- node_modules/axios/index.d.ts   1985-10-26 09:15:00.000000000 +0100
+++ node_modules/openapi-client-axios/node_modules/axios/index.d.ts 1985-10-26 09:15:00.000000000 +0100
@@ -59,10 +59,10 @@
   responseType?: ResponseType;
   xsrfCookieName?: string;
   xsrfHeaderName?: string;
-  onUploadProgress?: (progressEvent: any) => void;
-  onDownloadProgress?: (progressEvent: any) => void;
+  onUploadProgress?: (progressEvent: ProgressEvent) => void;
+  onDownloadProgress?: (progressEvent: ProgressEvent) => void;
   maxContentLength?: number;
-  validateStatus?: ((status: number) => boolean) | null;
+  validateStatus?: ((status: number) => boolean | null);
   maxBodyLength?: number;
   maxRedirects?: number;
   socketPath?: string | null;

I don't really understand why there is such a difference, but, well, it would be nice if the validateStatus signature was compatible.

npdev453 commented 3 years ago

@mat813, there are no guaranties that openapi-client-axios will use the same version of the axios that you used to provide AxiosRequestConfig from the root package. So, that error is expected and will show you all incompatibilities if you will use wrong config (during type-checking stage).

So, at first one, I do not see any reason to forcing that type because ts will resolve it automatically as type from 'openapi-client-axios'. But anyway if you or your linter prefer no-any everywhere you should get that type for a client type version that really will be used, as example:

api.init().then((client) => {
    type UseFullfiedParameters = Parameters<typeof client.interceptors.request.use>[0]
    type OAAxiosRequestConfig = Parameters<UseFullfiedParameters>[0]
        
    client.interceptors.request.use(
        (config: OAAxiosRequestConfig ): OAAxiosRequestConfig => { ... }
      )
})

At the second one, openapi-client-axios was recently updated to use the latest axios, could help, but not in perfectly way in my mind.

anttiviljami commented 3 years ago

Hi @mat813, @npdev453 axios is now used as a peerDependency, which should solve the issue (or at least make the behaviour clearer).

Feel free to contact me if there are still issues regarding this!