Skip to content

[BUG][TypeScript-Fetch] Incorrect code generation for oneOf schema with number | string types #21259

@tobq

Description

@tobq

The TypeScript-Fetch generator produces incorrect code for a schema that uses oneOf to define a type as either a number or a string. The generated *ToJSONTyped function (e.g., MyCustomSpeedToJSONTyped) returns an empty object {} instead of the actual value when the input value is not null. This leads to incorrect serialization of this type.

The problematic generated code for a type MyCustomSpeed = number | string; is:

/* tslint:disable */
/* eslint-disable */
/**
 * My API
 * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
 *
 * The version of the OpenAPI document: v1
 *
 *
 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 * https://openapi-generator.tech
 * Do not edit the class manually.
 */

/**
 * @type MyCustomSpeed
 * MyCustomSpeed is either a numeric percentage or a predefined string.
 * @export
 */
export type MyCustomSpeed = number | string;

export function MyCustomSpeedFromJSON(json: any): MyCustomSpeed {
    return MyCustomSpeedFromJSONTyped(json, false);
}

export function MyCustomSpeedFromJSONTyped(json: any, ignoreDiscriminator: boolean): MyCustomSpeed {
    if (json == null) {
        return json;
    }
    // The following line is also problematic for FromJSON, it should attempt to parse
    // json as number or string, not return an empty object.
    return {} as any;
}

export function MyCustomSpeedToJSON(value?: MyCustomSpeed | null): any {
    return MyCustomSpeedToJSONTyped(value, false);
}

export function MyCustomSpeedToJSONTyped(value?: MyCustomSpeed | null, ignoreDiscriminator: boolean = false): any {
    if (value == null) {
        return value;
    }
    // This line is incorrect, it should return 'value'
    return {};
}
openapi-generator version

The openapitools.json file indicates version 7.13.0 of generator-cli.

{
  "$schema": "./node_modules/@openapitools/openapi-generator-cli/config.schema.json",
  "spaces": 2,
  "generator-cli": {
    "version": "7.13.0"
  }
}
OpenAPI declaration file content or url

Here's a minimal OpenAPI 3.0 spec to reproduce the issue:

openapi: 3.0.1
info:
  title: Minimal API for Bug Report
  version: v1
paths:
  /test:
    post:
      summary: Test endpoint with MyCustomSpeed
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TestPayload'
      responses:
        '200':
          description: OK
components:
  schemas:
    MyNumericValue:
      type: number
      description: A numeric value (e.g., 0 to 1).
    MyCustomSpeed:
      oneOf:
        - $ref: '#/components/schemas/MyNumericValue'
        - type: string
          enum:
            - "fixed-value-a"
            - "fixed-value-b"
      description: A value that can be a number or a specific string.
    TestPayload:
      type: object
      properties:
        speed_setting:
          $ref: '#/components/schemas/MyCustomSpeed'
Generation Details

The generator is invoked via a script in package.json:

"scripts": {
  "generate-sdk": "openapi-generator-cli generate -i path/to/your/openapi.yml -g typescript-fetch -o output_directory"
}

Replace path/to/your/openapi.yml with the actual path to the OpenAPI spec and output_directory with the desired output folder.

Steps to reproduce
  1. Save the minimal OpenAPI spec above as minimal-openapi.yml.
  2. Ensure you have @openapitools/openapi-generator-cli version 7.13.0 (or potentially other affected versions).
  3. Run the command: openapi-generator-cli generate -i minimal-openapi.yml -g typescript-fetch -o ./generated-sdk
  4. Inspect the generated file generated-sdk/models/MyCustomSpeed.ts.
  5. Observe that MyCustomSpeedToJSONTyped returns {} instead of value.
  6. Observe that MyCustomSpeedFromJSONTyped returns {} instead of attempting to parse the input.
Related issues/PRs

(Please search existing issues on the OpenAPI Generator GitHub repository for similar problems before submitting. If you find any, link them here.)

Suggest a fix

The MyCustomSpeedToJSONTyped function should directly return the value if it's not null, as number and string are already valid JSON types.

export function MyCustomSpeedToJSONTyped(value?: MyCustomSpeed | null, ignoreDiscriminator: boolean = false): any {
    if (value == null) {
        return value;
    }
    // Proposed fix:
    return value;
}

For MyCustomSpeedFromJSONTyped, it needs to correctly handle the oneOf case. Since number and string are primitive types, a simple check should suffice, or it should at least return the input json to be processed by the calling code, rather than an empty object. A more robust solution would be to attempt to match the type.

export function MyCustomSpeedFromJSONTyped(json: any, ignoreDiscriminator: boolean): MyCustomSpeed {
    if (json == null) {
        return json;
    }
    // Proposed fix (simple version, assumes json is already the correct primitive type):
    // More sophisticated type checking could be added if necessary,
    // but for number | string, direct return is often sufficient if upstream validation is done.
    // Alternatively, one could attempt to parse or validate against number and the enum strings.
     if (typeof json === 'number' || typeof json === 'string') { // Add more specific checks for string enums if needed
        return json as MyCustomSpeed;
    }
    // Fallback or error if type doesn't match, instead of empty object
    // For example, throw an error or return the json as is for the caller to handle.
    // Returning json as is:
    return json;
    // Or, to be stricter and closer to typical oneOf handling:
    // try {
    //     // Attempt to validate/deserialize as number
    //     const numVal = MyNumericValueFromJSONTyped(json, true); // Assuming MyNumericValue is just 'number'
    //     return numVal;
    // } catch (e) {
    //     // ignore
    // }
    // try {
    //     // Attempt to validate/deserialize as string enum
    //     if (typeof json === 'string' && (json === "fixed-value-a" || json === "fixed-value-b")) {
    //         return json as string;
    //     }
    // } catch (e) {
    //     // ignore
    // }
    // throw new Error(`No match found in MyCustomSpeedFromJSONTyped for ${JSON.stringify(json)}`);
}

The exact implementation for FromJSONTyped might vary based on how strictly oneOf for primitives should be handled, but returning {} is incorrect. The simplest correct behavior would be return json;.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions