Openapi-generator: oneOf not generating union class properties Typescript-Angular

Created on 4 Jun 2019  路  5Comments  路  Source: OpenAPITools/openapi-generator

Description

I am using the example provided in the tests for oneOf. Once I try to generate for typescript-angular I get the three classes:

// apple.ts
export interface Apple { 
    kind?: string;
}

// banana.ts
export interface Banana { 
    count?: number;
}

// fruit.ts
import { Apple } from './apple';
import { Banana } from './banana';

export type Fruit = Apple | Banana;

As you can see the color property of fruit is missing.

openapi-generator version

I was using version 4.0.1 with the docker version.

Docker image used was:

openapitools/openapi-generator-cli@sha256:d67438016ccf3067655eb12ce23aab2b6f3e89f916cd153ae9874251af82b3e2
OpenAPI declaration file content or url
openapi: 3.0.1
info:
   title: fruity
   version: 0.0.1
paths:
   /:
      get:
         responses:
            '200':
               description: desc
               content:
                  application/json:
                     schema:
                        $ref: '#/components/schemas/fruit'
components:
   schemas:
      fruit:
         title: fruit
         properties:
            color:
               type: string
         oneOf:
            - $ref: '#/components/schemas/apple'
            - $ref: '#/components/schemas/banana'
      apple:
         title: apple
         type: object
         properties:
            kind:
               type: string
      banana:
         title: banana
         type: object
         properties:
            count:
               type: number
Command line used for generation
docker run --rm -v ${PWD}:/local openapitools/openapi-generator-cli@sha256:d67438016ccf3067655eb12ce23aab2b6f3e89f916cd153ae9874251af82b3e2 generate \
-i /local/input.yaml \
-g typescript-angular \
-c /local/config.json \
-o /local

Content of config.json is:

{
    "apiPackage": "api",
    "ngVersion": "6"
}
Steps to reproduce

Execute the test file using the provided command.

TypeScript Bug

Most helpful comment

Similar issues here. With a schema like:

      AssetList
        ...  
        items:
          type: array
          items:
            discriminator:
              propertyName: assetType
            oneOf:
              - $ref: '#/components/schemas/BackgroundReference'
              - $ref: '#/components/schemas/EmbellishmentReference'
              - $ref: '#/components/schemas/LayoutReference'
              - $ref: '#/components/schemas/MaskReference'

I'm seeing TypeScript compilation errors like:

src/assetList.ts:14:92 - error TS2307: Cannot find module './oneOfBackgroundReferenceEmbellishmentReferenceLayoutReferenceMaskReference'.

14 import { OneOfBackgroundReferenceEmbellishmentReferenceLayoutReferenceMaskReference } from './oneOfBackgroundReferenceEmbellishmentReferenceLayoutReferenceMaskReference';

I'm seeing this with primitives as well:

    LayoutReference:
      allOf:
        - $ref: '#/components/schemas/AssetReference'
        - type: object
          properties:
            ...
            layout:
              oneOf:
                - type: string
                - type: object

TypeScript error:

src/layoutReference.ts:17:35 - error TS2307: Cannot find module './oneOfstringobject'.

17 import { OneOfstringobject } from './oneOfstringobject';

All 5 comments

馃憤 Thanks for opening this issue!
馃彿 I have applied any labels matching special text in your issue.

The team will review the labels and make any necessary changes.

I found a few other things of note regarding the oneOf TypeScript client generator.

I'm getting the same output as @ealtuna with the given example.

Is that the expected behavior given a top level oneOf definition?

This example would make more sense to me:

components:
   schemas:
      fruit:
         title: fruit
         properties:
            color:
               type: string
            value:
               oneOf:
                  - $ref: '#/components/schemas/apple'
                  - $ref: '#/components/schemas/banana'

That version looks like it will work properly but the generated oneOf model files are not generated

Output:

// Fruit.ts
...
import {
    OneOfapplebanana, // Does not exist 
    OneOfapplebananaFromJSON,
    OneOfapplebananaToJSON,
} from './';

/**
 * 
 * @export
 * @interface Fruit
 */
export interface Fruit {
    /**
     * 
     * @type {string}
     * @memberof Fruit
     */
    color?: string;
    /**
     * 
     * @type {OneOfapplebanana}
     * @memberof Fruit
     */
    value?: OneOfapplebanana;
}
...

One last issue I ran into was that primitive data types are ignored when they are used in oneOf definitions.

ex.

components:
   schemas:
      fruit:
         title: fruit
         properties:
            color:
               type: string
         oneOf:
            - $ref: '#/components/schemas/apple'
            - $ref: '#/components/schemas/banana'
            - string
            - integer

outputs:

// Fruit.ts

import {
    Apple,
    Banana,
} from './';

/**
 * @type Fruit
 * @export
 */
export type Fruit = Apple | Banana; // Expected string | integer here as well

Same issue exists in the typescript-fetch generator, the OneOf* functions don't get generated, but referenced leading to a compilation error :(

Similar issues here. With a schema like:

      AssetList
        ...  
        items:
          type: array
          items:
            discriminator:
              propertyName: assetType
            oneOf:
              - $ref: '#/components/schemas/BackgroundReference'
              - $ref: '#/components/schemas/EmbellishmentReference'
              - $ref: '#/components/schemas/LayoutReference'
              - $ref: '#/components/schemas/MaskReference'

I'm seeing TypeScript compilation errors like:

src/assetList.ts:14:92 - error TS2307: Cannot find module './oneOfBackgroundReferenceEmbellishmentReferenceLayoutReferenceMaskReference'.

14 import { OneOfBackgroundReferenceEmbellishmentReferenceLayoutReferenceMaskReference } from './oneOfBackgroundReferenceEmbellishmentReferenceLayoutReferenceMaskReference';

I'm seeing this with primitives as well:

    LayoutReference:
      allOf:
        - $ref: '#/components/schemas/AssetReference'
        - type: object
          properties:
            ...
            layout:
              oneOf:
                - type: string
                - type: object

TypeScript error:

src/layoutReference.ts:17:35 - error TS2307: Cannot find module './oneOfstringobject'.

17 import { OneOfstringobject } from './oneOfstringobject';

i think its not supported to have top level properties and oneOf. you should include the color: type: string on each schema

but its true that even like this, the union type FromJSON and ToJSON are not being generated.

the individuals FromJSON and ToJSON to each oneOf are being generated.

it seems that when there's a discriminator its not creating the top level functions FromJSON and ToJSON to choose between the underlying oneOf types base on that discriminator

{
    "title": "Reserve Deal Vehicle Request",
    "oneOf": [
        { "$ref": "reserve_deal_vehicle_email.json#" },
        { "$ref": "reserve_deal_vehicle_phone.json#" }
    ],
    "discriminator": {
        "propertyName": "type",
        "mapping": {
            "email": "reserve_deal_vehicle_email.json",
            "sms": "reserve_deal_vehicle_phone.json"
        }
    }
}
{
    "title": "Reserve Deal Vehicle Request Email",
    "type": "object",
    "required": ["first_name", "last_name", "email"],
    "properties": {
        "email": { "type": "string", "format": "email" },
        "type": { "const": "email" }
    }
}
{
    "title": "Reserve Deal Vehicle Request Phone",
    "type": "object",
    "required": ["first_name", "last_name", "phone"],
    "properties": {
        "phone": { "type": "string" },
        "type": { "const": "sms" }
    }
}

result:

import {
    RequestsReserveDealVehicleEmail,
    RequestsReserveDealVehiclePhone,
} from './';

export type RequestsReserveDealVehicle = RequestsReserveDealVehicleEmail | RequestsReserveDealVehiclePhone;

// No top level FromJson and ToJson
export interface RequestsReserveDealVehicleEmail { 
    email: string; 
    type?: RequestsReserveDealVehicleEmailTypeEnum;
}

export function RequestsReserveDealVehicleEmailFromJSON(json: any): RequestsReserveDealVehicleEmail {
    return {
        'email': json['email'],
        'type': !exists(json, 'type') ? undefined : json['type'],
    };
}

export function RequestsReserveDealVehicleEmailToJSON(value?: RequestsReserveDealVehicleEmail): any {
    if (value === undefined) {
        return undefined;
    }
    return {
        'email': value.email,
        'type': value.type,
    };
}

export enum RequestsReserveDealVehicleEmailTypeEnum {
    Email = 'email'
}
export interface RequestsReserveDealVehiclePhone {
    phone: string;
    type?: RequestsReserveDealVehiclePhoneTypeEnum;
}

export function RequestsReserveDealVehiclePhoneFromJSON(json: any): RequestsReserveDealVehiclePhone {
    return {
        'phone': json['phone'],
        'type': !exists(json, 'type') ? undefined : json['type'],
    };
}

export function RequestsReserveDealVehiclePhoneToJSON(value?: RequestsReserveDealVehiclePhone): any {
    if (value === undefined) {
        return undefined;
    }
    return {
        'phone': value.phone,
        'type': value.type,
    };
}

export enum RequestsReserveDealVehiclePhoneTypeEnum {
    Sms = 'sms'
}

We need a FromJSON and ToJSON thats uses the discriminator to choose between one or the other

Was this page helpful?
0 / 5 - 0 ratings