swagger-api / swagger-codegen

swagger-codegen contains a template-driven engine to generate documentation, API clients and server stubs in different languages by parsing your OpenAPI / Swagger definition.
http://swagger.io
Apache License 2.0
17.04k stars 6.03k forks source link

[Client: typescript-angular] Array with OneOff generates Array<ModelObject>, but ModelObject is not defined. #8372

Closed codessentials closed 5 years ago

codessentials commented 6 years ago
Description

When generating typescript-angular code for the provided yaml, the code generates an interface that references ModelObject, but that class/interface is not generated.

Swagger-codegen version

3.0.0: version at https://editor.swagger.io/ on july/2/2018

Swagger declaration file content or url

Abstract:

    Employees:
      properties:
        values:
          type: array
          items:
            oneOf:
              - $ref: '#/components/schemas/Lawyer'
              - $ref: '#/components/schemas/Clerk'

Full yaml: https://gist.github.com/codessentials/7122ab4a8e37a8621f9c4546d9d382a4

Command line used for generation

Just used the online swagger editor.

Steps to reproduce

You will see this:

import { ModelObject } from './modelObject';

export interface Employees { 
    values?: Array<ModelObject>;
}

The class/interface ModelObject is not generated.

I'm curious to how this interface would have to be generated in order to be able to distinguish between the two different types. How will one be able to generate a different layout in case of a Layer or a Clerk?

Related issues/PRs

Is the above another use-case for generating classes as described in https://github.com/swagger-api/swagger-codegen/issues/6546 ? If the array contains actual class instances of Clerk and Lawyer, one can write code using instanceof.

Suggest a fix/enhancement

In case we keep using interfaces, I guess there should be generated something like this:

import { Lawyer} from './lawyer';
import { Clerk} from './clerk';

export interface Employees { 
    values?: Array<Lawyer | Clerk>;
}
davidsimonboyd commented 5 years ago

Confirming that we also have the exact same problem. We're currently working around it by hacking the generated files manually :(

Could this be looked at soon please?

walakulu commented 5 years ago

Same issue happened when I try to generate typescript client stubs using openapi: "3.0.0".

Jarkko-10Duke commented 5 years ago

swagger-codegen-cli 3.0.4 has the same issue

jimidle commented 5 years ago

Is this likely to get fixed, and if not, does anyone have a fix, such as what should go in modelObject.ts.

It looks to me like this happens when an API call can accept different body types (which might be wrong in the first place) or when an API can return 200 { some body data}, or 400 {empty body}.

I guess it should be generating a model that defines each of the possible types.

micaelboucard commented 5 years ago

Also related to this issue: https://github.com/swagger-api/swagger-codegen/issues/9339

samkohli commented 5 years ago

I have the same issue. When is this getting fixed?

themcoo commented 5 years ago

codegen 3.0.13, issue still persists, together with other year+ old issues....

HugoMario commented 5 years ago

@themcoo , time to fix it, dont you think? :)

blackstarzes commented 5 years ago

@HugoMario the ModelObject that is created will be created multiple times if the current suggested approach is taken. Would a better approach be the one discussed in the linked issue https://github.com/swagger-api/swagger-codegen/issues/9339 ?

HugoMario commented 5 years ago

@blackstarzes , that's the best approach to me.

HugoMario commented 5 years ago

this is fixed by https://github.com/swagger-api/swagger-codegen-generators/pull/531, closing now, but please let me know if you get something wrong and i'll reopen it.

kanguran commented 4 years ago

I have got it repeated on swagger-codegen-cli-3.0.14.jar import { ModelObject } from '../model/modelObject';

receiving next error because modelObject was not generated under model folder. All the objects were generated fine. error TS2307: Cannot find module '../model/modelObject'.

HugoMario commented 4 years ago

Hi @kanguran, that error was recently fixed but it's ot included in 3.0.14 release.

marc-wilson commented 4 years ago

Looks like it's fixed in 3.0.16. Was getting ModelObject in 3.0.13 but after upgrading to 3.0.16 we are looking good!

kanguran commented 4 years ago

Hi. Nice fixes, we still have some issues even on 3.0.16. Our Angular Application was started on Angular 2 Alpha, now we upgraded to Angular 6.1 from 5.2 , cannot upgrade futher as have to switch to Typescript3. Our Angular app is complex, we have 3 different backends, to each of them connect over REST. First backend, currently runs on SpringBoot 2.1 Codegen gen V3 is able compile generated code from it. Second backend, which runs on the top of Camunda and Spring boot 2.1 most complicated service codegen compilation outcomes in 2 errors a) V3.0.16 Library still generated unneeded import import { ModelObject } from '../model/modelObject'; build error TS2307: Cannot find module '../model/modelObject'. b) formParams.append('documents', element) issue

documents.forEach((element) => {
    formParams = formParams.append('documents', <any>element) || formParams;
})

build error TS1345: An expression of type 'void' cannot be tested for truthiness

Third backend V3 codegen build has also 1 build error related to Enums handling: build error TS2345: Argument of type 'NotificationSearchFilter' is not assignable to parameter of type 'string'.

export namespace NotificationSearchFilter {
    export type StatusEnum = 'STATUS1' | ' STATUS2' | ' STATUS3' | ' STATUS4' | ' STATUS5';
    export const StatusEnum = {
        STATUS1: ' STATUS1' as StatusEnum,
        STATUS2: ' STATUS2' as StatusEnum,
        STATUS3: ' STATUS3' as StatusEnum,
        STATUS4: ' STATUS4' as StatusEnum,
        STATUS5: ' STATUS5' as StatusEnum
    };
}

/**
 * Searches notifications by parameters and resends to new receiver.
 * 
 * @param body newReceiver
 * @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
 * @param reportProgress flag to report request and response progress.
 */
public resendByFilter(body?: string, observe?: 'body', reportProgress?: boolean): Observable<any>;
public resendByFilter(body?: string, observe?: 'response', reportProgress?: boolean): Observable<HttpResponse<any>>;
public resendByFilter(body?: string, observe?: 'events', reportProgress?: boolean): Observable<HttpEvent<any>>;
public resendByFilter(body?: string, observe: any = 'body', reportProgress: boolean = false ): Observable<any> {

resendByFilter(resendingForm: NotificationSearchFilter, newReceiver: string): Observable<{}> {
  return this.notificationApi.resendByFilter(resendingForm, newReceiver);
}

We are waiting for your fixes, so we can continue upgrade to Angular 8, it will be again huge refactoring as PrimeNG refactored tables, so we will have to redevelop our html templates.

HugoMario commented 4 years ago

@kanguran, can you please file a new issue and ping me there, i'll work on it asap. I just dont want to add more updates to a closed one.