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

[BUG][Typescript] Generated code with `oneOf` does not properly check the dto type

Open artemka-debug opened this issue 1 year ago • 0 comments

Bug Report Checklist

  • [x] Have you provided a full/minimal spec to reproduce the issue?
  • [x] Have you validated the input using an OpenAPI validator (example)?
  • [x] Have you tested with the latest master to confirm the issue still exists?
  • [ ] Have you searched for related issues/PRs?
  • [x] What's the actual output vs expected output?
  • [ ] [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description

Given the OpenApi schema below, we have Dto with payload field, which has a type of oneOf of Payload1, Payload2 and Payload3. Each of payload types has a property type with type of enum with only one value.

When we generate client code, we get this code in models/DtoPayload.ts file:

export function DtoPayloadToJSON(value?: DtoPayload | null): any {
    if (value == null) {
        return value;
    }

    if (instanceOfPayload1(value)) {
        return Payload1ToJSON(value as Payload1);
    }
    if (instanceOfPayload2(value)) {
        return Payload2ToJSON(value as Payload2);
    }
    if (instanceOfPayload3(value)) {
        return Payload3ToJSON(value as Payload3);
    }

    return {};
}

and code for each if check:

models/Payload1.ts

export function instanceOfPayload1(value: object): boolean {
    if (!('type' in value)) return false;
    if (!('barcode' in value)) return false;
    return true;
}

models/Payload2.ts

export function instanceOfPayload2(value: object): boolean {
    if (!('type' in value)) return false;
    return true;
}

models/Payload3.ts

export function instanceOfPayload3(value: object): boolean {
    if (!('type' in value)) return false;
    if (!('barcode' in value)) return false;
    return true;
}

since functions instanceOfPayload1 and instanceOfPayload3 are identical, generated code treats Payload3 as Payload1, which causes problems when converting plain objects to dto's.

openapi-generator version

7.5.0

OpenAPI declaration file content or url
{
  "openapi": "3.0.0",
  "paths": {
    "/endpoint": {
      "get": {
        "operationId": "endpoint",
        "summary": "endpoint",
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Dto"
                }
              }
            }
          }
        },
        "security": [
          {
            "access-token": []
          }
        ]
      }
    }
  },
  "info": {
    "title": "API",
    "description": "API",
    "version": "1.0",
    "contact": {},
    "license": {
      "name": "UNLICENSED",
      "url": "UNLICENSED"
    }
  },
  "tags": [],
  "servers": [
  ],
  "components": {
    "securitySchemes": {
      "access-token": {
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "type": "http",
        "description": "JWT Authorization header using the Bearer scheme."
      }
    },
    "schemas": {
      "Payload3": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "AGE_VERIFICATION"
            ]
          },
          "barcode": {
            "type": "string"
          },
          "requiredAge": {
            "type": "number"
          }
        },
        "required": [
          "type",
          "barcode"
        ]
      },
      "Payload2": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "ASSISTANCE_REQUESTED"
            ]
          }
        },
        "required": [
          "type"
        ]
      },
      "Payload1": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "PARTIAL_RESCAN"
            ]
          },
          "barcode": {
            "type": "string"
          }
        },
        "required": [
          "type",
          "barcode"
        ]
      },
      "Dto": {
        "type": "object",
        "properties": {
          "payload": {
            "description": "Payload for the assistance request",
            "oneOf": [
              {
                "$ref": "#/components/schemas/Payload1"
              },
              {
                "$ref": "#/components/schemas/Payload2"
              },
              {
                "$ref": "#/components/schemas/Payload3"
              }
            ]
          }
        },
        "required": [
          "payload"
        ]
      }
    }
  }
}
Generation Details

npx -y @openapitools/openapi-generator-cli generate -g typescript-fetch
--additional-properties=importFileExtension=".js" --skip-validate-spec
-i ./test.json
-o src/api-client

Steps to reproduce
  1. make directory: test
  2. cd into directory test
  3. create file test.json and copy and paste provided api schema above.
  4. run provided in Generation Details command in cli
Related issues/PRs
Suggest a fix

We want the generator to also take into account types of fields, when checking if object is instance of another object.

for example:

export function instanceOfPayload1(value: object): boolean {
    if (!('type' in value && value.type === Object.values(Payload1TypeEnum)[0])) return false;
    if (!('barcode' in value)) return false;
    return true;
}

artemka-debug avatar May 20 '24 12:05 artemka-debug