openapi-typescript icon indicating copy to clipboard operation
openapi-typescript copied to clipboard

Discriminator mapping does not seem to work properly

Open ivansky opened this issue 1 year ago • 0 comments

Description Discriminator + Enums does not work, there are a few problems.

Name Version
openapi-typescript 7.0.0-rc.0
Node.js v18.17.1
OS + version macOS

Reproduction

openapi: 3.0.1
info:
  title: API
  version: v1
servers:
  - url: http://localhost:8082
    description: Generated server url
paths:
  /api/pets:
    get:
      operationId: getPets
      summary: Get pets
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Pet'
components:
  schemas:
    PetType:
      type: string
      enum:
        - Dog
        - Cat
        - Lizard
    Pet:
      type: object
      required:
        - petType
      properties:
        petType:
          $ref: '#/components/schemas/PetType'
      discriminator:
        propertyName: petType
        mapping:
          Dog: '#/components/schemas/Dog'
          Cat: '#/components/schemas/Cat'
          Lizard: '#/components/schemas/Lizard'
    Cat:
      allOf:
        - $ref: '#/components/schemas/Pet'
        - type: object
          # all other properties specific to a `Cat`
          properties:
            name:
              type: string
    Dog:
      allOf:
        - $ref: '#/components/schemas/Pet'
        - type: object
          # all other properties specific to a `Dog`
          properties:
            bark:
              type: string
    Lizard:
      allOf:
        - $ref: '#/components/schemas/Pet'
        - type: object
          # all other properties specific to a `Lizard`
          properties:
            lovesRocks:
              type: boolean

npx openapi-typescript@next ./testapi.yaml -o ./testapi.ts --enum=true Results in:

export interface paths {
    "/api/pets": {
        parameters: {
            query?: never;
            header?: never;
            path?: never;
            cookie?: never;
        };
        /** Get pets */
        get: operations["getPets"];
        put?: never;
        post?: never;
        delete?: never;
        options?: never;
        head?: never;
        patch?: never;
        trace?: never;
    };
}
export type webhooks = Record<string, never>;
export interface components {
    schemas: {
        /** @enum {string} */
        PetType: PetType;
        Pet: {
            petType: components["schemas"]["PetType"];
        };
        Cat: Omit<components["schemas"]["Pet"], "petType"> & {
            name?: string;
        } & {
            /**
             * @description discriminator enum property added by openapi-typescript
             * @enum {string}
             */
            petType: CatPetType;
        };
        Dog: Omit<components["schemas"]["Pet"], "petType"> & {
            bark?: string;
        } & {
            /**
             * @description discriminator enum property added by openapi-typescript
             * @enum {string}
             */
            petType: DogPetType;
        };
        Lizard: Omit<components["schemas"]["Pet"], "petType"> & {
            lovesRocks?: boolean;
        } & {
            /**
             * @description discriminator enum property added by openapi-typescript
             * @enum {string}
             */
            petType: LizardPetType;
        };
    };
    responses: never;
    parameters: never;
    requestBodies: never;
    headers: never;
    pathItems: never;
}
export type $defs = Record<string, never>;
export interface operations {
    getPets: {
        parameters: {
            query?: never;
            header?: never;
            path?: never;
            cookie?: never;
        };
        requestBody?: never;
        responses: {
            /** @description OK */
            200: {
                headers: {
                    [name: string]: unknown;
                };
                content: {
                    "application/json": components["schemas"]["Pet"][];
                };
            };
        };
    };
}
export enum PetType {
    Dog = "Dog",
    Cat = "Cat",
    Lizard = "Lizard"
}
export enum CatPetType {
    Cat = "Cat"
}
export enum DogPetType {
    Dog = "Dog"
}
export enum LizardPetType {
    Lizard = "Lizard"
}

Expected result

Cat: Omit<components["schemas"]["Pet"], "petType"> & {
    name?: string;
} & {
    /**
     * @description discriminator enum property added by openapi-typescript
     * @enum {string}
     */
    petType: CatPetType;
};
  • Instead of CatPetType better to have PetType.Cat
  • Exclude Omit<components["schemas"]["Pet"], "petType"> from the type to get rid of cycle type dependency Cat -> Pet -> Cat that causes typescript error

Preferred outcome

Cat: {
    name?: string;
} & {
    petType: PetType.Cat;
};

Checklist

ivansky avatar Jun 19 '24 15:06 ivansky