openapi-typescript-codegen icon indicating copy to clipboard operation
openapi-typescript-codegen copied to clipboard

Discriminators not working for oneOf when the members are allOf schemas

Open gillchristian opened this issue 3 years ago • 9 comments

Great tool! Thanks for all the effort.

While generating an API I found out discriminators aren't working for oneOf schemas that consist of a list of schemas that themselves are composed with allOf.

It's not easy to explain with a few words. I create a repository that reproduces the issue and explained in more detail in the readme there, comparing a working example and the case that fails.

https://github.com/gillchristian/openapi-typescript-codegen-discriminator-report

gillchristian avatar Mar 17 '22 10:03 gillchristian

@gillchristian I'm currently stuck with the same issue. Have you found a workaround for making this work in the meantime?

leolabs avatar Mar 31 '22 10:03 leolabs

That's a good solution!

I've come up with another one that could be helpful for some. By removing the DiscriminatorType and using enums with just one entry for the discriminated type, you can get the codegen to generate valid code.

An example, based on your example code:

components:
  schemas:
    Base:
      type: object
      required:
        - id
      properties:
        id:
          type: string
    One:
      allOf:
        - '$ref': '#/components/schemas/Base'
        - type: object
          required:
            - tag
            - one
          properties:
            tag:
              type: string
              enum: [one]
            one:
              type: string
    Two:
      allOf:
        - '$ref': '#/components/schemas/Base'
        - type: object
          required:
            - tag
            - two
          properties:
            tag:
              type: string
              enum: [two]
            two:
              type: string
    DiscriminatorComplex:
      discriminator:
        propertyName: tag
        mapping:
          one: '#/components/schemas/One'
          two: '#/components/schemas/Two'
      oneOf:
        - '$ref': '#/components/schemas/One'
        - '$ref': '#/components/schemas/Two'

If you want the DiscriminatorType as a type in TS, you can export it with:

export type DiscriminatorType = DiscriminatorComplex["tag"];

leolabs avatar Mar 31 '22 16:03 leolabs

We also encountered this issue. The workarounds don't scale that well. You need a lot of extra code that can also introduce errors. It would be really nice if the generation would respect the discriminators.

Xyaren avatar Jun 29 '22 12:06 Xyaren

any progress on this?

nir-bar-zvi avatar Aug 25 '22 10:08 nir-bar-zvi

If this is implemented, it will be the only typescript client generator that works for my use case.

benlongo avatar Oct 09 '22 01:10 benlongo

In the meantime, I've coped with the limitation by writing a transformation that inlines the allOf. The result is structurally equivalent in terms of the resulting types.

benlongo avatar Oct 13 '22 13:10 benlongo

It seems this would be expressible via an intersection & on the base type with an Omit on the discriminator field to prevent widening it back to string.

benlongo avatar Oct 13 '22 23:10 benlongo