openapi-typescript-codegen
openapi-typescript-codegen copied to clipboard
oneof enum generates incorrect code
Hi!
this model
"VendingItemState": {
"oneOf": [
{
"type": "object",
"required": [
"type"
],
"properties": {
"type": {
"type": "string",
"enum": [
"Pending"
]
}
}
},
{
"type": "object",
"required": [
"type"
],
"properties": {
"type": {
"type": "string",
"enum": [
"Picked"
]
}
}
},
{
"type": "object",
"required": [
"type"
],
"properties": {
"type": {
"type": "string",
"enum": [
"Placed"
]
}
}
},
{
"type": "object",
"required": [
"content",
"type"
],
"properties": {
"content": {
"type": "string",
"format": "date-time"
},
"type": {
"type": "string",
"enum": [
"Dispensed"
]
}
}
},
{
"type": "object",
"required": [
"content",
"type"
],
"properties": {
"content": {
"type": "array",
"items": [
{
"type": "string",
"format": "date-time"
},
{
"type": "string"
}
],
"maxItems": 2,
"minItems": 2
},
"type": {
"type": "string",
"enum": [
"Error"
]
}
}
}
]
},
generates the following code:
export type VendingItemState = ({
type: VendingItemState.type;
} | {
content: string;
type: VendingItemState.type;
} | {
content: Array<any>;
type: VendingItemState.type;
});
export namespace VendingItemState {
export enum type {
PENDING = 'Pending',
}
}
which is missing most of the options for "type"...
@v-morlock hey, are you able to replicate the same issue in @nicolas-chaulet/openapi-typescript-codegen?
Hi! Unfortunately yes
@v-morlock uh, I see what's happening. What's the output you'd expect? Roll all those options into a single enum, or multiple enums per each option?
Both would be fine to me - the value is representing a rust enum that looks like this:
#[derive(Serialize, Deserialize, Clone, schemars::JsonSchema, Eq, PartialEq, Debug)]
#[serde(tag = "type", content = "content")]
pub enum VendingItemState {
Pending,
Picked,
Placed,
Dispensed(chrono::DateTime<Utc>),
Error(chrono::DateTime<Utc>, String),
}
so i think the direct mapping would be sth like below - one could make an argument that a separate enum isn't really necessary for enums with only a single value. But in practice, anything that gives the same end-result as the structure below would be fine to me. I don't think I'd ever really use the generated enum anyway. I think a single enum wouldn't work though because then it wouldn't be clear which options contain additional values and which don't.
export type VendingItemState = ({
type: "Pending";
} | {
type: "Picked";
} | {
type: "Placed";
} | {
type: "Dispensed;
content: string;
} | {
type: "Error";
content: Array<any>;
});
Btw, do you have an idea why the "content" array is typed as "any"?
@v-morlock Got it, thanks! This is an interesting case, will have a look at it, but it will be available in the package I shared above as this one isn't really maintained
@v-morlock please try with the latest version of @nicolas-chaulet/openapi-typescript-codegen
🎉
That should give you exactly what you need
export type ModelWithOneOfEnum = {
foo: 'Bar';
} | {
foo: 'Baz';
} | {
foo: 'Qux';
} | {
content: string;
foo: 'Quux';
} | {
content: [string | string];
foo: 'Corge';
};
@v-morlock I updated @nicolas-chaulet/openapi-typescript-codegen
so it should now work out of the box. It is a huge change set, so I'd love if you could upgrade and let me know if anything breaks!
@v-morlock how did you generate your OpenAPI specification?
Hi! Thanks for developing that fix and sorry that I haven't found the time to test it yet. The spec is generated by the library "aide" for rust / axum
@v-morlock for the minItems/maxItems array, would you be okay with output [Date | string, Date | string]
?