Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Typescript client generation with anyOf, oneOf, allOf #3388

Open
danielbecroft opened this issue Mar 31, 2021 · 6 comments
Open

Typescript client generation with anyOf, oneOf, allOf #3388

danielbecroft opened this issue Mar 31, 2021 · 6 comments

Comments

@danielbecroft
Copy link

We're currently building out an OpenAPI specification for a legacy system (so handcrafted, no automated API generation), for use from an Angular application. We've used the allOf and oneOf constructs a few times, but have just found that the NSwag generation isn't quite supportive of these.

As a basic example (using constructs from the OpenAPI documentation):

paths:
  /pets:
    patch:
      requestBody:
        content:
          application/json:
            schema:
              oneOf:
                - $ref: '#/components/schemas/Cat'
                - $ref: '#/components/schemas/Dog'
              discriminator:
                propertyName: pet_type
      responses:
        '200':
          description: Updated
components:
  schemas:
    Pet:
      type: object
      required:
        - pet_type
      properties:
        pet_type:
          type: string
      discriminator:
        propertyName: pet_type
    Dog:     # "Dog" is a value for the pet_type property (the discriminator value)
      allOf: # Combines the main `Pet` schema with `Dog`-specific properties 
        - $ref: '#/components/schemas/Pet'
        - type: object
          # all other properties specific to a `Dog`
          properties:
            bark:
              type: boolean
            breed:
              type: string
              enum: [Dingo, Husky, Retriever, Shepherd]
    Cat:     # "Cat" is a value for the pet_type property (the discriminator value)
      allOf: # Combines the main `Pet` schema with `Cat`-specific properties 
        - $ref: '#/components/schemas/Pet'
        - type: object
          # all other properties specific to a `Cat`
          properties:
            hunts:
              type: boolean
            age:
              type: integer

Is giving us:

/**
 * @param body (optional) 
 * @return Updated
 */
pets(body: Cat | undefined): Promise<void> {
	let url_ = this.baseUrl + "/pets";
	url_ = url_.replace(/[?&]$/, "");

	const content_ = JSON.stringify(body);

	let options_ = <RequestInit>{
		body: content_,
		method: "PATCH",
		headers: {
			"Content-Type": "application/json",
		}
	};

	return this.http.fetch(url_, options_).then((_response: Response) => {
		return this.processPets(_response);
	});
}

Notice that the pets() method is only accepting a strongly typed Cat instance, or an undefined. No Dog. If I generate classes instead of interfaces, I can see the generation using the pet_type field to construct the correct instance from the Pet class:

    static fromJS(data: any, _mappings?: any): Pet | null {
        data = typeof data === 'object' ? data : {};
        if (data["pet_type"] === "Cat")
            return createInstance<Cat>(data, _mappings, Cat);
        if (data["pet_type"] === "Dog")
            return createInstance<Dog>(data, _mappings, Dog);
        return createInstance<Pet>(data, _mappings, Pet);
    }

But the pets() method is still the same. It's only accepting one of the strongly typed classes.

Is this expected? Is there any method of getting allOf, oneOf to generate correctly with using a TypeScript client.

I've seen past issues with comments that it should be working, as TypeScript is more flexible than C#, but it doesn't appear to be working for us.

Using v13.10.8.0.

@jeremyVignelles
Copy link
Collaborator

Yes, that's a known issue, though I wasn't able to find an issue to duplicate this with.
I think that the real issue is in NJsonSchema's typescript generatore instead of here, but there might be some impact here as well.

@RicoSuter
Copy link
Owner

Ref: RicoSuter/NJsonSchema#13

@nardo7
Copy link

nardo7 commented Nov 29, 2021

Something new about this Issue? Some workarounds?

@ghost
Copy link

ghost commented Sep 7, 2022

I just ran into this as well, with a more complex setup

@Dementiy
Copy link

Dementiy commented Jun 8, 2023

Is there any progress on this issue?

@Schwaller
Copy link

This is causing quite some problem when you mix Springdoc with Jackson deserialisation. Basically we have to write them manually and not use annotations for Jackson because else these oneOf() allOf() of simple polymorphism messes up the JS/TS code ... would be amazing if you could fix that!
Or maybe I understand it wrong and this is indeed invalid OpenAPI definition?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants