openapi-typescript
openapi-typescript copied to clipboard
Incorrect type generation when using a `$ref` with `discriminator` inside `allOf`
Preamble
Thank you for your work on this project, keep up the good work!
Description
A wrong type is generated when using a $ref
from schemas
that contains a discriminator
inside an allOf
.
An invalid Omit
occurs and removes the discriminator to force a "json" value string.
Name | Version |
---|---|
openapi-typescript |
6.7.1 |
Node.js | 18.18.2 |
OS + version | Windows 11 |
Reproduction
This following OpenAPI json will produce the following invalid type:
content: {
"application/json": {
my_type: "json";
} & Omit<components["schemas"]["allData"], "my_type">;
};
{
"openapi": "3.0.0",
"info": {
"version": "1.0.0",
"title": "openapi-typescript bug reproduction",
"license": {
"name": "DWTFYW",
"url": "https://en.wikipedia.org/wiki/WTFPL"
}
},
"servers": [
{
"url": "n/a"
}
],
"paths": {
"/performRequest": {
"post": {
"security": [],
"operationId": "performRequest",
"summary": "POST /performRequest",
"parameters": [],
"responses": {
"200": {
"description": "POST /performRequest",
"content": {
"application/json": {
"schema": {
"title": "performRequest Response",
"allOf": [
{
"$ref": "#/components/schemas/allData"
}
]
}
}
}
},
"400": {
"description": "Bad Request"
}
}
}
}
},
"components": {
"schemas": {
"allData": {
"type": "object",
"discriminator": {
"propertyName": "my_type"
},
"required": ["my_type"],
"oneOf": [
{ "$ref": "#/components/schemas/data1" },
{ "$ref": "#/components/schemas/data2" }
]
},
"data1": {
"type": "object",
"properties": {
"my_type": {
"type": "string",
"enum": ["data_type_ex_1"]
}
},
"required": ["my_type"]
},
"data2": {
"type": "object",
"properties": {
"my_type": {
"type": "string",
"enum": ["data_type_ex_2"]
}
},
"required": ["my_type"]
}
}
}
}
Expected result
content: {
"application/json": components["schemas"]["allData"];
};
Remark
Taking the content of the $ref
and putting it in the allOf
works correctly, but the problem seems to be specific to the use of a $ref
in a allOf
.
The bug seems to occur from 6.6.1.
Checklist
- [X] My OpenAPI schema passes the Redocly validator (
npx @redocly/cli@latest lint
) - [ ] I’m willing to open a PR (see CONTRIBUTING.md)
I believe we are seeing this same issue (or a similar issue), but with the $ref
appearing inside an anyOf
rather than allOf
. I can try to provide a minimal repro if that is helpful.
P.S.: +1 thank you for this library! It's super helpful for our application.
Again, great job with this package! It's the perfect solution to our use case!
And yes, can confirm this bug is occurring in 7.0.0-next.8
too.
It's incorrectly omitting the property used as a discriminator.
OpenApi YML:
ObjectOne:
type: object
additionalProperties: false
oneOf:
- $ref: '#/components/schemas/Bar'
- $ref: '#/components/schemas/Baz'
discriminator:
propertyName: foo
mapping:
bar: '#/components/schemas/Bar'
baz: '#/components/schemas/Baz'
Actual TS:
AnotherObject: {
arrayOfObjectOnes?: (Omit<components["schemas"]["ObjectOne"], "foo"> & Record<string, never>)[];
}
Expected TS:
AnotherObject: {
arrayOfObjectOnes?: components["schemas"]["ObjectOne"][];
}
I might be completely out of my depth here, but I think the bug might be coming from here?
https://github.com/drwpow/openapi-typescript/blob/92f4b96f655538adf366a7e380f8a93b536f65fa/packages/openapi-typescript/src/transform/schema-object.ts#L190-L194
I am not too familiar with discriminators, I wanted to ask if the problem I am seeing has the same root cause of this issue? Thanks!
The generated chatCompletionRequestMessage
type (with 7.0.0-next.8
) from this spec is missing the discriminator mappings?
chatCompletionRequestMessage: {
role: components["schemas"]["chatCompletionRequestMessageRole"];
// no mappings here?
};
chatCompletionRequestMessageRole: "system" | "user" | "assistant" | "tool" | "function";
The mapping types are generated correctly though, for now I use this workaround:
type chatCompletionRequestMessage = (
| components['schemas']['chatCompletionRequestMessageSystem']
| components['schemas']['chatCompletionRequestMessageUser']
| components['schemas']['chatCompletionRequestMessageAssistant']
| components['schemas']['chatCompletionRequestMessageTool']
| components['schemas']['chatCompletionRequestMessageFunction']
);
I am not too familiar with discriminators, I wanted to ask if the problem I am seeing has the same root cause of this issue? Thanks!
I don't think this is the same issue. If it were, you'd be seeing an Omit<...>
in the generated code
I believe i'm still seeing this issue
Any updates on this? I just encountered it