orval-labs / orval

orval is able to generate client with appropriate type-signatures (TypeScript) from any valid OpenAPI v3 or Swagger v2 specification, either in yaml or json formats. 🍺
https://orval.dev
MIT License
3.18k stars 336 forks source link

Polymorphic schema with 'useNativeEnums' leads to 'never' enum discriminator field #1662

Open MGabr opened 1 month ago

MGabr commented 1 month ago

What are the steps to reproduce this issue?

  1. Add a api-docs.yaml spec with a polymorphic schema :

    openapi: 3.0.1
    info:
      title: OpenAPI definition
      version: v0
    servers:
      - url: http://localhost:8080
        description: Generated server url
    paths:
      /pet:
        get:
          tags:
            - pet-controller
          operationId: getPet
          responses:
            "200":
              description: OK
              content:
                '*/*':
                  schema:
                    $ref: "#/components/schemas/Pet"
    components:
      schemas:
        Cat:
          required:
            - type
          type: object
          allOf:
            - $ref: "#/components/schemas/Pet"
            - type: object
              properties:
                lives:
                  type: integer
                  format: int32
        Dog:
          required:
            - type
          type: object
          allOf:
            - $ref: "#/components/schemas/Pet"
            - type: object
              properties:
                age:
                  type: integer
                  format: int32
        Pet:
          required:
            - type
          type: object
          properties:
            type:
              type: string
              enum:
                - DOG
                - CAT
          discriminator:
            propertyName: type
            mapping:
              DOG: "#/components/schemas/Dog"
              CAT: "#/components/schemas/Cat"
  2. Add a config orval.config.js with useNativeEnums: true

     module.exports = {
       'api-docs-file': {
         input: './api-docs.yaml',
         output: {
           target: './api-orval.ts',
           override: {
             useNativeEnums: true,
           }
         }
       },
     };
  3. Generate types with orval --config orval.config.js.

  4. Add a TypeScript file api-orval-types-test.ts that uses the types:

    import {Dog, DogType} from './api-orval';
    
    const dog: Dog = {
        type: DogType.DOG,
        age: 7,
    };
  5. Run tsc api-orval.ts api-orval-types-test.ts

What happens?

The following model gets generated:

export enum PetType {
  DOG= 'DOG',
  CAT= 'CAT',
}

export interface Pet {
  type: PetType;
}

export enum DogType {
  DOG= 'DOG',
}

export type DogAllOf = {
  age?: number;
};

export type Dog = Pet & DogAllOf & {
  type: DogType;
};

So there are two different types for the type field of Dog. PetType for Pet and DogType for Dog.

This leads to the following TypeScript errors:

Type 'import("api-orval").DogType' is not assignable to type 'never'.
Type 'number' is not assignable to type 'never'.

What were you expecting to happen?

No TypeScript errors.

Types like the following being generated:

export enum PetType {
  DOG= 'DOG',
  CAT= 'CAT',
}

export interface Pet {
  type: PetType;
}

export type DogAllOf = {
  age?: number;
};

export type Dog = Pet & DogAllOf & {
  type: PetType.DOG;
};

What versions are you using?

  System:
    OS: Windows 11 10.0.26100
    CPU: (12) x64 AMD Ryzen 5 3600X 6-Core Processor
    Memory: 17.26 GB / 31.95 GB
  npmPackages:
    axios: ^1.7.7 => 1.7.7
    orval: ^7.1.1 => 7.1.1
    typescript: ^5.6.2 => 5.6.2