Skip to content

Referencing a type with discriminator generates wrong type #1116

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

Closed
1 task done
sregg opened this issue May 18, 2023 · 7 comments
Closed
1 task done

Referencing a type with discriminator generates wrong type #1116

sregg opened this issue May 18, 2023 · 7 comments
Labels
bug Something isn't working openapi-ts Relevant to the openapi-typescript library

Comments

@sregg
Copy link

sregg commented May 18, 2023

Description

When adding an Owner type that references a Pet in discriminator (oneOf) test case like so:

Owner: {
  type: "object",
  properties: {
    favoritePet: {
      nullable: true,
      allOf: [
        { $ref: "#/components/schemas/Pet" },
      ],
    },
  },
}

the generated type is wrong:

Owner: {
  favoritePet?: ({
    petType: "Owner";
  } & Omit<components["schemas"]["Pet"], "petType">) | null;
};

instead of

Owner: {
  favoritePet?: components["schemas"]["Pet"];
};
Name Version
openapi-typescript 6.2.4

Reproduction

See PR: sregg#1

Expected result

See error message in: https://github.com/sregg/openapi-typescript/actions/runs/5009218680/jobs/8977922547?pr=1

Checklist

@sators
Copy link

sators commented May 18, 2023

+1

@mitchell-merry
Copy link
Contributor

Could you provide a full example of a schema? So we can reproduce this

@sregg
Copy link
Author

sregg commented May 19, 2023

The example is in my fork:
https://github.com/sregg/openapi-typescript/pull/1/files#diff-825cc17817d6be362cee3768df588ac6fa8ee329b4b8990dcc85767d8ad3cf3b

const schema: OpenAPI3 = {
        openapi: "3.1",
        info: { title: "test", version: "1.0" },
        components: {
          schemas: {
            Pet: {
              oneOf: [
                { $ref: "#/components/schemas/Cat" },
                { $ref: "#/components/schemas/Dog" },
                { $ref: "#/components/schemas/Lizard" },
              ],
              discriminator: {
                propertyName: "petType",
                mapping: {
                  cat: "#/components/schemas/Cat",
                  dog: "#/components/schemas/Dog",
                  lizard: "#/components/schemas/Lizard",
                },
              },
            },
            Cat: {
              type: "object",
              properties: {
                name: { type: "string" },
                petType: { type: "string", enum: ["cat"] },
              },
              required: ["petType"],
            },
            Dog: {
              type: "object",
              properties: {
                bark: { type: "string" },
                petType: { type: "string", enum: ["dog"] },
              },
              required: ["petType"],
            },
            Lizard: {
              type: "object",
              properties: {
                lovesRocks: { type: "boolean" },
                petType: { type: "string", enum: ["lizard"] },
              },
              required: ["petType"],
            },
            Owner: {
              type: "object",
              properties: {
                favoritePet: {
                  nullable: true,
                  allOf: [
                    { $ref: "#/components/schemas/Pet" },
                  ],
                },
              },
            }
          },
        },
      };

@drwpow drwpow added openapi-ts Relevant to the openapi-typescript library bug Something isn't working labels May 22, 2023
@drwpow
Copy link
Contributor

drwpow commented Jul 25, 2023

So I looked into this, and this is slightly in-conflict with #1016, which allows users to use discriminators without explicitly adding it to the discriminator.mapping (test). Will look to see if a fix is possible without undoing that change.

@drwpow
Copy link
Contributor

drwpow commented Jul 25, 2023

I actually think the generated types are correct. From the spec:

In scenarios where the value of the discriminator field does not match the schema name or implicit mapping is not possible, an optional mapping definition MAY be used

In other words, the mapping is optional, and the spec allows for implicit mapping, of which petType: "Owner" is the correct inference. So I believe this is behaving as the discriminator object has been designed to work.

As a workaround you could shorten your schema to:

Owner:
  type: object
  properties:
    favoritePet:
      $ref: "#/components/schemas/Pet"

Which would produce

favoritePet?: components["schemas"]["Pet"];

The only difference being the missing | null, but the optional key may be close enough.

If I’m mistaken, then please take a look at this existing allOf test in the test suite which is currently passing, and compare it to how the spec is described. I believe the two match, and is identical to the schema you posted. But if I’ve missed something in the spec, or if you can point out a discrepancy between the two, I’m happy to revisit this.

@drwpow
Copy link
Contributor

drwpow commented Aug 1, 2023

Going to close this issue as I believe this is working as intended (the definition of discriminators is just tricky). But again, open to feedback if I’m mistaken in this.

@drwpow drwpow closed this as completed Aug 1, 2023
@sregg
Copy link
Author

sregg commented Aug 2, 2023

You're right. I'm not sure why our Micronaut BE generates this schema:

activePaymentMethod:
  nullable: true
  allOf:
    - $ref: '#/components/schemas/CustomerPaymentMethod'

instead of this:

activePaymentMethod:
  nullable: true
  $ref: '#/components/schemas/CustomerPaymentMethod'

I'll try to fix the BE then.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working openapi-ts Relevant to the openapi-typescript library
Projects
None yet
Development

No branches or pull requests

4 participants