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-angular] Bug - Parameters named "responseType" cause conflict. #5853

Closed
SandroBuerki opened this issue Apr 7, 2020 · 16 comments · Fixed by #9202 or #9216
Closed

[typescript-angular] Bug - Parameters named "responseType" cause conflict. #5853

SandroBuerki opened this issue Apr 7, 2020 · 16 comments · Fixed by #9202 or #9216

Comments

@SandroBuerki
Copy link

Description

If you name a parameter responseType (or response_type etc.) the generated client method signature expects a parameter called responseType. However, the generated code of such method declares a variable responseType, which causes the compiler to throw the error message Duplicate identifier 'responseType'.

Method signature:
public authorize(responseType?: 'code', state?: string, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: undefined}): Observable<any> {

Variable declaration:
let responseType: 'text' | 'json' = 'json';

openapi-generator version

v4.3.0 - It jused to work with v4.2.3

OpenAPI declaration file content or url

###swagger.json

{
  "swagger": "2.0",
  "info": {
    "title": "Example swagger",
    "description": "Example description",
    "version": "1.0.0"
  },
  "paths": {
    "\/oauth\/auth": {
      "get": {
        "operationId": "authorize",
        "parameters": [
          {
            "name": "response_type",
            "in": "query",
            "type": "string",
            "enum": [
              "code"
            ]
          }
        ],
        "responses": {
          "302": {
            "description": "Redirection to Authentication flow or straight to the redirect_uri if the authentication has been completed before"
          }
        }
      }
    }
  }
}
Command line used for generation

docker run --rm -v ${PWD}:/local openapitools/openapi-generator-cli generate
-i /local/swagger.json
-g typescript-angular
-o /local/out
--additional-properties modelPropertyNaming=original,ngVersion=9.0.0,npmVersion=1.0.0,npmName=@package/scope,npmRepository=https://gitlab.com/api/v4/projects/123/packages/npm/

Steps to reproduce
  • Create a swagger.json with the content as shown above
  • Execute the command as shown above
  • See the method signature of authenticate() generated in out/api/oAuth.service.ts
Related issues/PRs

No similar issues, but the PR which changed the behavior. It swapped the logic of toVarName() and toParamName(): #5427

Suggest a fix/enhancement

With 4.2.3, the method parameter kept its case. Due to a change in 4.3.0, all parameters are now camelized. I could probably fix the code myself, and I'm willing to open a PR. I'm just not sure what you guys think the best way would be:

  • Should modelPropertyNaming affect the parameter name?
  • Should I add responseType as a reserved word?
  • Should I just rename the responseType variable inside the generated function?
  • Or am I completely wrong and something else is needed?

Best regards, and thanks a lot in advance.

@auto-labeler
Copy link

auto-labeler bot commented Apr 7, 2020

👍 Thanks for opening this issue!
🏷 I have applied any labels matching special text in your issue.

The team will review the labels and make any necessary changes.

@FaKleiser
Copy link

We have also stumbled into this issue and would be glad if this could be resolved. We have a parameter named response_type in our API definition.

@amakhrov
Copy link
Contributor

Thanks for the detailed problem description and the suggestions!

Should modelPropertyNaming affect the parameter name?

I think that the conflict is possible regardless on that. Even if we do not camelize the param name in the generator, it's still possible that the api-spec itself has the name in camel case that matches exactly the local variable name.

Should I add responseType as a reserved word?

This would probably do the trick. I see that AbstractTypeScriptClientCodegen already lists a couple of such local variable names as reserved:

// local variable names used in API methods (endpoints)
"varLocalPath", "queryParameters", "headerParams", "formParams", "useFormData", "varLocalDeferred",

Looks like each individual typescript generator (Angular, Fetch, etc) should add to this list its own set of local var names specific to that generator's templates

Should I just rename the responseType variable inside the generated function?

Can fix your particular case, but still has a conflict potential with other api specs that can define arbitrary param names

@Adelrisk
Copy link

Should I add responseType as a reserved word?

This would probably do the trick. I see that AbstractTypeScriptClientCodegen already lists a couple of such local variable names as reserved:

I'd be interested to know if this can be achieved as an "end user" of this plugin/tool. Is there any way to configure this without forking and re-publishing code?

The query parameter response_type is a required query parameter of oauth 2.0, so dealing with this is more than a "nice to have": https://tools.ietf.org/html/rfc6749#section-3.1.1

The current workaround is to downgrade to 4.2.3 and set modelPropertyNaming to original. (Thanks to @SandroBuerki)

@orosro
Copy link

orosro commented Oct 8, 2020

I'm encountering the same issue using @latest version (4.3.x I think). In any case, setting modelPropertyNaming=snake_case was not working. Same scenario, required param of oAuth2.

I used the same workaround as the others, downgrading to 4.2.3 and setting the modelPropertyNaming to original.

Any updates? A lot of time passed

@vdumitraskovic
Copy link

Maybe related...

Using a typescript-axios generator on a parameter named query is generating duplicate identifier. ATM I don't know any workarounds.

@jk89
Copy link

jk89 commented Nov 26, 2020

+1 seeing this issue in all modern versions of openapi cli. The only working version for me on npm is "1.0.18-4.2.3" with additional properties of "supportsES6=true", "withInterfaces=true", "modelPropertyNaming=original", "useSingleRequestParameter=true". Unfortunately this version is not capable of making an api.module.ts compatible with angular version 10.x.x. due to ModuleWithProviders needing to be post typed. Meaning the the workaround is no longer viable!

So anyone who has an angular 10+ project and wants a client for a service which implements oauth2 will not be able to use the cli tool at all.

Can the client not just have some prefix for internal variable to avoid collision in the namespace of parameters? Or some other simple defensive technique? Its comes across as very strange that this is such a systemic issue.

I also see other issues with:
error TS2552: Cannot find name 'queryParameters'. Did you mean 'VREyeParameters'
where i have an authentication type api_key query parameter apiKey:
"type": "apiKey",
"scheme": "apiKey",
"name": "api_key",
"in": "query"

So if i have a route with no query parameters but a security query parameter the codegen tool does not create the QueryParameter variable and it end up confused looking for VREyeParameters.

@sudall
Copy link

sudall commented Jan 8, 2021

I'm also seeing a similar issue in typescript-axios with a parameter named options conflicting with the options: any = {} that gets generated on all parameter creator functions.

@sandermvanvliet
Copy link

I have a similar problem with the regular typescript generator.

We have a request parameter with the name from which conflicts with the rxjsStubs definition for the from method leading to build errors like this on npm run build:

types/ObservableAPI.ts:885:35 - error TS2349: This expression is not callable.
  Type 'Number' has no call signatures.

885     let middlewarePreObservable = from<RequestContext>(requestContextPromise);
                                      ~~~~

@grking8
Copy link
Contributor

grking8 commented Apr 7, 2021

Having similar issue and workaround of downgrading version and changing modelPropertyNaming to original also worked

However, above not really a viable solution for me so have submitted #9202 to try and resolve

@zijam
Copy link

zijam commented Apr 8, 2021

With merge #9202, I get following error when building my Angular v11 project :

Error: src/backend/api/providers.service.ts:128:17 - error TS2769: No overload matches this call.
  Overload 1 of 15, '(url: string, options: { headers?: HttpHeaders | { [header: string]: string | string[]; } | undefined; observe: "events"; params?: HttpParams | { [param: string]: string | string[]; } | undefined; reportProgress?: boolean | undefined; responseType?: "json" | undefined; withCredentials?: boolean | undefined; }): Observable<...>', gave the following error.
    Argument of type '{ responseType_: any; withCredentials: boolean | undefined; headers: HttpHeaders; observe: any; reportProgress: boolean; }' is not assignable to parameter of type '{ headers?: HttpHeaders | { [header: string]: string | string[]; } | undefined; observe: "events"; params?: HttpParams | { [param: string]: string | string[]; } | undefined; reportProgress?: boolean | undefined; responseType?: "json" | undefined; withCredentials?: boolean | undefined; }'.
      Object literal may only specify known properties, but 'responseType_' does not exist in type '{ headers?: HttpHeaders | { [header: string]: string | string[]; } | undefined; observe: "events"; params?: HttpParams | { [param: string]: string | string[]; } | undefined; reportProgress?: boolean | undefined; responseType?: "json" | undefined; withCredentials?: boolean | undefined; }'. Did you mean to write 'responseType'?
  Overload 2 of 15, '(url: string, options: { headers?: HttpHeaders | { [header: string]: string | string[]; } | undefined; observe: "response"; params?: HttpParams | { [param: string]: string | string[]; } | undefined; reportProgress?: boolean | undefined; responseType?: "json" | undefined; withCredentials?: boolean | undefined; }): Observable<...>', gave the following error.
    Argument of type '{ responseType_: any; withCredentials: boolean | undefined; headers: HttpHeaders; observe: any; reportProgress: boolean; }' is not assignable to parameter of type '{ headers?: HttpHeaders | { [header: string]: string | string[]; } | undefined; observe: "response"; params?: HttpParams | { [param: string]: string | string[]; } | undefined; reportProgress?: boolean | undefined; responseType?: "json" | undefined; withCredentials?: boolean | undefined; }'.
      Object literal may only specify known properties, but 'responseType_' does not exist in type '{ headers?: HttpHeaders | { [header: string]: string | string[]; } | undefined; observe: "response"; params?: HttpParams | { [param: string]: string | string[]; } | undefined; reportProgress?: boolean | undefined; responseType?: "json" | undefined; withCredentials?: boolean | undefined; }'. Did you mean to write 'responseType'?
  Overload 3 of 15, '(url: string, options?: { headers?: HttpHeaders | { [header: string]: string | string[]; } | undefined; observe?: "body" | undefined; params?: HttpParams | { [param: string]: string | string[]; } | undefined; reportProgress?: boolean | undefined; responseType?: "json" | undefined; withCredentials?: boolean | undefined; } | undefined): Observable<...>', gave the following error.
    Argument of type '{ responseType_: any; withCredentials: boolean | undefined; headers: HttpHeaders; observe: any; reportProgress: boolean; }' is not assignable to parameter of type '{ headers?: HttpHeaders | { [header: string]: string | string[]; } | undefined; observe?: "body" | undefined; params?: HttpParams | { [param: string]: string | string[]; } | undefined; reportProgress?: boolean | undefined; responseType?: "json" | undefined; withCredentials?: boolean | undefined; }'.
      Object literal may only specify known properties, but 'responseType_' does not exist in type '{ headers?: HttpHeaders | { [header: string]: string | string[]; } | undefined; observe?: "body" | undefined; params?: HttpParams | { [param: string]: string | string[]; } | undefined; reportProgress?: boolean | undefined; responseType?: "json" | undefined; withCredentials?: boolean | undefined; }'. Did you mean to write 'responseType'?
128                 responseType_: <any>responseType_,

code:

return this.httpClient.get<SocialMedia>(`${this.configuration.basePath}/providers/social`,
            {
                responseType_: <any>responseType_,
                withCredentials: this.configuration.withCredentials,
                headers: headers,
                observe: observe,
                reportProgress: reportProgress
            }
        );

HttpClient doesn't have a property named responseType_,

after manually removing trailing underscore, I can build my project again.

return this.httpClient.get<SocialMedia>(`${this.configuration.basePath}/providers/social`,
            {
                responseType: <any>responseType_,
                withCredentials: this.configuration.withCredentials,
                headers: headers,
                observe: observe,
                reportProgress: reportProgress
            }
        );

@macjohnny
Copy link
Member

@zijam thanks for reporting!
Do you want to file a PR to fix this? Otherwise I revert it.

@macjohnny macjohnny reopened this Apr 8, 2021
@zijam
Copy link

zijam commented Apr 8, 2021

@macjohnny I'm currently unable to file a PR now. Can you revert the changes for now.

@Ellfish
Copy link

Ellfish commented Jan 7, 2022

For anyone who comes across this, I found a workaround. I was having a similar issue with the typescript-axios options: AxiosRequestConfig parameter conflicting with my own options parameter.

Using the --template CLI option , I was able to rename options to _requestOptions in apiInner.mustache. Template docs: https://openapi-generator.tech/docs/templating/

I'm using v5.3.1, YMMV.

@JeanMeche
Copy link

+1 @Ellfish, this solved my problem too.
To download the templates locally you can use the following command (just replace typescript-angular with the generator of your choice).

mkdir -p .openapi-generator/templates/ && cd $_
curl -L https://api.github.com/repos/OpenAPITools/openapi-generator/tarball | tar xz
mv `ls`/modules/openapi-generator/src/main/resources/typescript-angular ./typescript-angular
\rm -rf OpenAPITools-openapi-generator-*
cd typescript-angular

@azorrozua
Copy link

This worked for me too, thanks!

Just replace options for _requestOptions everywhere in the file you find it and problem solved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment