Skip to content

fix: correctly generate anyOf on unions with string and boolean constant #2208

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

Open
wants to merge 1 commit into
base: next
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions src/TypeFormatter/LiteralUnionTypeFormatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,18 @@ export class LiteralUnionTypeFormatter implements SubTypeFormatter {
appendTypeValues(type, typeValues);
}

const schema = {
type: toEnumType(Array.from(typeNames)),
enum: Array.from(typeValues),
};

return preserveLiterals ? { anyOf: [{ type: "string" }, schema] } : schema;
const schema =
typeNames.size === 1 && typeValues.size === 1
? {
type: toEnumType(Array.from(typeNames)),
const: Array.from(typeValues)[0],
}
: {
type: toEnumType(Array.from(typeNames)),
enum: Array.from(typeValues),
};

return hasString ? { anyOf: [{ type: "string" }, schema] } : schema;
}

public getChildren(): BaseType[] {
Expand Down
6 changes: 6 additions & 0 deletions test/valid-data/type-union/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ type MyType4 = "s" | 1;
type MyType5 = "s" | 1[];
type MyType6 = ("s" | 1)[];

type MyType7 = string | true;
type MyType8 = "s" | true;

export interface TypeUnion {
var1: MyType1;
var2: MyType2;
Expand All @@ -14,4 +17,7 @@ export interface TypeUnion {
var4: MyType4;
var5: MyType5;
var6: MyType6;

var7: MyType7;
var8: MyType8;
}
25 changes: 24 additions & 1 deletion test/valid-data/type-union/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,27 @@
]
},
"type": "array"
},
"var7": {
"anyOf": [
{
"type": "string"
},
{
"const": true,
"type": "boolean"
}
]
},
"var8": {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm unsure if we can use enum and type[] in the same type. Especially the combination of boolean, string, and true.

I'd bet that even if allowed, this would break in a lot of community parsers. Could we make this be a anyOf boolean const true and string enum s?

Copy link
Author

@pixunil pixunil Mar 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn’t this the analog case for var4 and var6, apart from using a number instead of boolean?
regarding whether it is allowed, at least for type and enum I don’t see a indication that they are exclusive (https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-01#section-6.1.1). it feels a bit redundant to specify both, as enum implicitly specifies type

"enum": [
"s",
true
],
"type": [
"string",
"boolean"
]
}
},
"required": [
Expand All @@ -78,7 +99,9 @@
"var3",
"var4",
"var5",
"var6"
"var6",
"var7",
"var8"
],
"type": "object"
}
Expand Down
Loading