Skip to content

Circular reference when using inheritance & polymorhism with discriminator #1565

@clxandstuff

Description

@clxandstuff

Description

Not sure if this is a bug. I would like to confirm that types generation is possible with my schema

Typescript definitions are circular which results in "any" types.
Name Version
openapi-typescript 7.0.0 & 6.7.4
Node.js 18.18.1
OS + version macOS 13, Windows 11, etc.

Reproduction

Generate types with below schema.

openapi: 3.0.0
info:
  title: Test schema
  version: V1
paths:
  /resource:
    get:
      operationId: getResource
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PetOwner"
components:
  schemas:
    PetOwner:
      type: object
      properties:
        pet:
          $ref: "#/components/schemas/Pet"
      required:
        - pet
    Pet:
      type: object
      properties:
        petType:
          allOf:
            - $ref: "#/components/schemas/PetType"
          readOnly: true
      discriminator:
        propertyName: petType
        mapping:
          Cat: "#/components/schemas/Cat"
          Dog: "#/components/schemas/Dog"
      oneOf:
        - $ref: "#/components/schemas/Cat"
        - $ref: "#/components/schemas/Dog"
      required:
        - petType
    Cat:
      allOf:
        - $ref: "#/components/schemas/Pet"
        - type: object
          properties:
            name:
              type: string
          required:
            - name
    Dog:
      allOf:
        - $ref: "#/components/schemas/Pet"
        - type: object
          properties:
            bark:
              type: string
          required:
            - bark
    PetType:
      type: string
      enum:
        - Cat
        - Dog

It results in:

export interface components {
  schemas: {
    PetOwner: {
      pet: components["schemas"]["Pet"];
    };
    Pet: {
      petType: components["schemas"]["PetType"];
    } & (components["schemas"]["Cat"] | components["schemas"]["Dog"]);
    Cat: {
      petType: "Cat";
    } & Omit<components["schemas"]["Pet"], "petType"> & {
      name: string;
    };
    Dog: {
      petType: "Dog";
    } & Omit<components["schemas"]["Pet"], "petType"> & {
      bark: string;
    };
    /** @enum {string} */
    PetType: "Cat" | "Dog";
  };
  responses: never;
  parameters: never;
  requestBodies: never;
  headers: never;
  pathItems: never;
}

Expected result

I expect Cat & Dog to not reference Pet

export interface components {
  schemas: {
    PetOwner: {
      pet: components["schemas"]["Pet"];
    };
    Pet: {
      petType: components["schemas"]["PetType"];
    } & (components["schemas"]["Cat"] | components["schemas"]["Dog"]);
    Cat: {
      petType: "Cat";
    } & {
      name: string;
    };
    Dog: {
      petType: "Dog";
    } & {
      bark: string;
    };
    /** @enum {string} */
    PetType: "Cat" | "Dog";
  };
  responses: never;
  parameters: never;
  requestBodies: never;
  headers: never;
  pathItems: never;
}

so I can use types like this

import { components } from "./types"

const a = {} as components["schemas"]["PetOwner"];

if (a.pet.petType === 'Cat') {
    a.pet.name
} else {
    a.pet.bark
}

Is this possible with the current version? If not I can try to fix this, if you guide me where to start.

Checklist

  • My OpenAPI schema passes the Redocly validator (npx @redocly/cli@latest lint) - there are some unrelated license and security errors
  • I’m willing to open a PR (see CONTRIBUTING.md)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingopenapi-tsRelevant to the openapi-typescript librarystaletrickyComplex problem which requires deep knowledge of TS, OpenAPI, this project, or all three

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions