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

Discriminated union generated as null | null when property is nullable #63

Open
MalachiMackie opened this issue Nov 21, 2024 · 0 comments

Comments

@MalachiMackie
Copy link

Hi, I encountered an issue when generating a discriminated union type with npx openapicmd typegen. When the discriminated union is assigned as a nullable property, the type is generated as null | null. but when assigned as a nullable: false property, it's generated fine.

I managed to get a minimal reproduction with the following command and apidoc:

command

npx -y openapicmd typegen api-doc.json > client.ts

api-doc.json

{
  "openapi": "3.0.3",
  "info": {
    "title": "budgeting-backend",
    "description": "",
    "license": {
      "name": ""
    },
    "version": "0.1.0"
  },
  "paths": {},
  "components": {
    "schemas": {
      "Budget": {
        "type": "object",
        "required": [
	  "requiredTarget"
        ],
        "properties": {
          "nullableTarget": {
            "allOf": [
              {
                "$ref": "#/components/schemas/BudgetTarget1"
              }
            ],
            "nullable": true
          },
	  "requiredTarget": {
	    "allOf": [
	      {
	        "$ref": "#/components/schemas/BudgetTarget2"
	      }
	    ],
	    "nullable": false
	  }
        }
      },     
      "BudgetTarget1": {
        "oneOf": [
          {
            "type": "object",
            "required": [
              "target_amount",
              "type"
            ],
            "properties": {
              "target_amount": {
                "type": "number",
                "format": "float"
              },
              "type": {
                "type": "string",
                "enum": [
                  "OneTime"
                ]
              }
            }
          },
          {
            "type": "object",
            "required": [
              "target_amount",
              "type"
            ],
            "properties": {
              "target_amount": {
                "type": "number",
                "format": "float"
              },
              "type": {
                "type": "string",
                "enum": [
                  "Repeating"
                ]
              }
            }
          }
        ],
        "discriminator": {
          "propertyName": "type"
        }
      },
      "BudgetTarget2": {
        "oneOf": [
          {
            "type": "object",
            "required": [
              "target_amount",
              "type"
            ],
            "properties": {
              "target_amount": {
                "type": "number",
                "format": "float"
              },
              "type": {
                "type": "string",
                "enum": [
                  "OneTime"
                ]
              }
            }
          },
          {
            "type": "object",
            "required": [
              "target_amount",
              "type"
            ],
            "properties": {
              "target_amount": {
                "type": "number",
                "format": "float"
              },
              "type": {
                "type": "string",
                "enum": [
                  "Repeating"
                ]
              }
            }
          }
        ],
        "discriminator": {
          "propertyName": "type"
        }
      }
    }
  }
}

generated client.ts

import type {
  OpenAPIClient,
  Parameters,
  UnknownParamsObject,
  OperationResponse,
  AxiosRequestConfig,
} from 'openapi-client-axios';

declare namespace Components {
    namespace Schemas {
        export interface Budget {
            nullableTarget?: null | null;
            requiredTarget: {
                target_amount: number; // float
                type: "OneTime";
            } | {
                target_amount: number; // float
                type: "Repeating";
            };
        }
        export type BudgetTarget1 = null | null;
        export type BudgetTarget2 = {
            target_amount: number; // float
            type: "OneTime";
        } | {
            target_amount: number; // float
            type: "Repeating";
        };
    }
}

export interface OperationMethods {
}

export interface PathsDictionary {
}

export type Client = OpenAPIClient<OperationMethods, PathsDictionary>

export type Budget = Components.Schemas.Budget;
export type BudgetTarget1 = Components.Schemas.BudgetTarget1;
export type BudgetTarget2 = Components.Schemas.BudgetTarget2;

note that I had to copy BudgetTarget into two different schemas in order to demonstrate it generating correctly for requiredTarget. If they both reference the same schema, then both properties generate as null | null

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant