Skip to content

[BUG][Typescript] Incorrect response type handling for oneOf strategy  #9305

@dinobal

Description

@dinobal

Bug Report Checklist

  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator (example)?
  • Have you tested with the latest master to confirm the issue still exists?
  • Have you searched for related issues/PRs?
  • What's the actual output vs expected output?
  • [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description
  • Is there a way to not have a wrapper object as an input parameter and instead just take an union type?
  • The return types are correct but it seems not to be handled correctly, a bug perhaps?
  • If everything works as intended how can I change my schema so the generated client has a method that can parse the response and type it correctly?
openapi-generator version

5.1.0

OpenAPI declaration file content or url

specs.yaml

openapi: 3.0.1
info:
  title: Sample API
  description: Optional multiline or single-line description in [CommonMark](http://commonmark.org/help/) or HTML.
  version: 0.1.9
servers:
  - url: http://api.example.com/v1
    description: Optional server description, e.g. Main (production) server
  - url: http://staging-api.example.com
    description: Optional server description, e.g. Internal staging server for testing
paths:
  /pets:
    post:
      requestBody:
        content:
          application/json:
            schema:
              oneOf:
                - $ref: '#/components/schemas/Cat'
                - $ref: '#/components/schemas/Dog'
              discriminator:
                propertyName: pet_type
                mapping:
                  obj1: '#/components/schemas/Cat'
                  obj2: '#/components/schemas/Dog'
      responses:
        '200':
          description: Created
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/Cat'
                  - $ref: '#/components/schemas/Dog'
                discriminator:
                  propertyName: pet_type
                  mapping:
                    obj1: '#/components/schemas/Cat'
                    obj2: '#/components/schemas/Dog'
components:
  schemas:
    Pet:
      type: object
      required:
        - pet_type
      properties:
        pet_type:
          type: string
      discriminator:
        propertyName: pet_type
    Dog:
      type: object
      allOf:
        - $ref: '#/components/schemas/Pet'
        - type: object
      properties:
        bark:
          type: boolean
        breed:
          type: string
          enum: [Dingo, Husky, Retriever, Shepherd]
    Cat:
      type: object
      allOf:
        - $ref: '#/components/schemas/Pet'
        - type: object
      properties:
        hunts:
          type: boolean
        age:
          type: integer
Generation Details
java -jar openapi-generator-cli.jar generate -i specs.yaml -g typescript-fetch -o tsclient/
Output
...
export interface PetsPostRequest {
    catDog?: Cat | Dog;
}

/**
 * 
 */
export class DefaultApi extends runtime.BaseAPI {

    /**
     */
    async petsPostRaw(requestParameters: PetsPostRequest): Promise<runtime.ApiResponse<Cat | Dog>> {
        const queryParameters: any = {};

        const headerParameters: runtime.HTTPHeaders = {};

        headerParameters['Content-Type'] = 'application/json';

        const response = await this.request({
            path: `/pets`,
            method: 'POST',
            headers: headerParameters,
            query: queryParameters,
            body: Cat | DogToJSON(requestParameters.catDog),
        });

        return new runtime.JSONApiResponse(response, (jsonValue) => Cat | DogFromJSON(jsonValue));
    }

    /**
     */
    async petsPost(requestParameters: PetsPostRequest): Promise<Cat | Dog> {
        const response = await this.petsPostRaw(requestParameters);
        return await response.value();
    }
Expected, something like
async petsPostRaw(pet: Cat | Dog | undefined ): Promise<runtime.ApiResponse<Cat | Dog>> {
        const queryParameters: any = {};

        const headerParameters: runtime.HTTPHeaders = {};

        headerParameters['Content-Type'] = 'application/json';
        const response = await this.request({
            path: `/pets`,
            method: 'POST',
            headers: headerParameters,
            query: queryParameters,
            body: pet.petType === 'Cat' ? CatToJSON() : pet.petType === 'Dog' ? DogToJSON() : undefined,
        });

        return new runtime.JSONApiResponse(response, 
            (jsonValue) => {
            const typedValue = 
                pet.petType === 'Cat' ? CatFromJSON(jsonValue) 
                : pet.petType === 'Dog' ? DogFromJSON(jsonValue) 
                : undefined;

            if(!typedValue){
                throw new Error(`No type matching "${pet.petType}" found`);
            }
            
            return typedValue;
        });
    }

    /**
     */
    async petsPost(pet: Cat | Dog): Promise<Cat | Dog> {
        const response = await this.petsPostRaw(pet);
        return await response.value();
    }
Related issues/PRs
  • Probably more than one regarding oneOf, anyOf, allOf

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