OpenAPITools / openapi-generator

OpenAPI Generator allows generation of API client libraries (SDK generation), server stubs, documentation and configuration automatically given an OpenAPI Spec (v2, v3)
https://openapi-generator.tech
Apache License 2.0
21.66k stars 6.54k forks source link

[BUG][TYPESCRIPT] typescript-angularjs enum #6114

Open ext opened 4 years ago

ext commented 4 years ago
Description

Given an API with an enum:

foo:
  stype: string
  enum: [FOO, BAR]

the typescript-angularjs (and other typescript templates) generates enums such as:

export namespace Example {
  export enum FooEnum {
    FOO = <any> 'FOO',
    BAR = <any> 'BAR'
  }
}

I'm not sure about that <any> casting as it produces a different API than without it.

When compiling to .js/.d.ts the output is vastly different because of the <any> cast:

export namespace Example {
  export enum FooEnum {
    FOO,
    BAR
  }
}

This could be argued to be a bug in tsc but on the other hand I dont see the purpose of the casting and what the intended outcome is. By looking at just the type information both FOO and BAR can be anything so tsc is not entirely wrong either.

It also seems to differ with other typescript templates:

openapi-generator version

Tested 4.2.2 and 4.3.0, same issue.

OpenAPI declaration file content or url

openapi.yaml:

openapi: 3.0.0
info:
  title: foo
  version: 0.0.0
paths:
  /foo:
    post:
      requestBody:
        content:
          application/json;charset=utf-8:
            schema: {$ref: '#/components/schemas/Body'}
        required: true
      responses:
        '204':
          description: No Content
components:
  schemas:
    Body:
      type: object
      properties:
        foo:
          type: string
          enum: [FOO, BAR]

tsconfig.json:

{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "declaration": true,
    "outDir": "./dist",
    "lib": ["es2017", "dom"],
    "rootDir": "./src",
    "strict": true,
    "moduleResolution": "node",
    "esModuleInterop": true
  }
}
Command line used for generation
openapi-generator generate -g typescript-angularjs -i openapi.yaml -o src/typescript-angularjs
tsc
Steps to reproduce
  1. Create above files
  2. Run commands from above
  3. Check created files in dist/typescript-angularjs/model/Body.d.ts
Suggest a fix

I personally think the cast should be removed and I dont see what it intends to solve. I can gladly create a PR to fix this if someone can acknowledge the issue.

auto-labeler[bot] commented 4 years ago

👍 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.

amakhrov commented 4 years ago

A notable difference is that using <any> makes TS to treat this enum as a numeric enum, which means the compiled JS code includes both forward and reverse lookup (https://www.typescriptlang.org/play?jsx=0&ts=3.7.5#code/KYOwrgtgBAYg9nAouaBvAUFKBBKBeKAHgEMQBPAPigHIAhagGk1gHkX8jTKbbsAlaugC+6dKEiwEySACYoGLLgJ1GzGGw51+gkUA)

This doesn't matter if enum keys are the same as values, like in your example (FOO = "FOO"). But in a real generated code it's not always the case (e.g. if using enumPropertyNaming generator option other than "original", or when a value is not a valid identifier).

I personally find this <any> awkward - and have recently got rid of it in our project.

congwenma commented 3 years ago

@amakhrov Hi how did you get rid of the <any> in your project? is there an openapi-generator configuration?

amakhrov commented 3 years ago

We use a custom template, which we pass to the generator via --template-dir command line argument.

congwenma commented 3 years ago

Is there an open-source location to the custom template? Our team are running into conflicting type issues resulting from enums generated from this <any> running through typescript-node, it would be awesome to use either a configuration or if not then the custom template for generating enums that matches our expectation.

amakhrov commented 3 years ago

Built-in templates for typescript-node are here: https://github.com/OpenAPITools/openapi-generator/tree/master/modules/openapi-generator/src/main/resources/typescript-node And here is the line that adds those <any> typer assertions: https://github.com/OpenAPITools/openapi-generator/blob/master/modules/openapi-generator/src/main/resources/typescript-node/model.mustache#L62

When you provide custom templates via --template-dir, this dir doesn't have to have ther full set of templates. You can only have a single one there that is tweaked for your needs (model.mustache in this case), and for everything else use built-in files.