Skip to content

Commit a24054f

Browse files
joshuatavaly
authored andcommitted
fix: Correct oneOf required option
BREAKING CHANGE: This changes the produced JSON schema for required `oneOf` types to correctly include it in the resulting `required` properties array.
1 parent a9c7086 commit a24054f

File tree

3 files changed

+76
-24
lines changed

3 files changed

+76
-24
lines changed

src/__tests__/schema.test.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,8 @@ describe('schema', () => {
501501
},
502502
{ required: true }
503503
),
504+
oneOfOptional: types.oneOf([types.number(), types.string()]),
505+
oneOfRequired: types.oneOf([types.number(), types.string()], { required: true }),
504506
stringOptional: types.string(),
505507
stringRequired: types.string({ required: true }),
506508
},
@@ -651,6 +653,26 @@ describe('schema', () => {
651653
},
652654
type: 'object',
653655
},
656+
oneOfOptional: {
657+
oneOf: [
658+
{
659+
type: 'number',
660+
},
661+
{
662+
type: 'string',
663+
},
664+
],
665+
},
666+
oneOfRequired: {
667+
oneOf: [
668+
{
669+
type: 'number',
670+
},
671+
{
672+
type: 'string',
673+
},
674+
],
675+
},
654676
stringOptional: {
655677
type: 'string',
656678
},
@@ -673,6 +695,7 @@ describe('schema', () => {
673695
'objectGenericRequired',
674696
'objectIdRequired',
675697
'objectRequired',
698+
'oneOfRequired',
676699
'stringRequired',
677700
'createdAt',
678701
'updatedAt',
@@ -707,6 +730,8 @@ describe('schema', () => {
707730
objectIdRequired: ObjectId;
708731
objectOptional?: { foo?: number };
709732
objectRequired: { foo?: number };
733+
oneOfOptional?: number | string;
734+
oneOfRequired: number | string;
710735
stringOptional?: string;
711736
stringRequired: string;
712737
createdAt: Date;
@@ -809,6 +834,8 @@ describe('schema', () => {
809834
},
810835
{ required: true }
811836
),
837+
oneOfOptional: types.oneOf([types.number(), types.string()]),
838+
oneOfRequired: types.oneOf([types.number(), types.string()], { required: true }),
812839
stringOptional: types.string({ required: false }),
813840
stringRequired: types.string({ required: true }),
814841
},
@@ -959,6 +986,26 @@ describe('schema', () => {
959986
},
960987
type: 'object',
961988
},
989+
oneOfOptional: {
990+
oneOf: [
991+
{
992+
type: 'number',
993+
},
994+
{
995+
type: 'string',
996+
},
997+
],
998+
},
999+
oneOfRequired: {
1000+
oneOf: [
1001+
{
1002+
type: 'number',
1003+
},
1004+
{
1005+
type: 'string',
1006+
},
1007+
],
1008+
},
9621009
stringOptional: {
9631010
type: 'string',
9641011
},
@@ -981,6 +1028,7 @@ describe('schema', () => {
9811028
'objectGenericRequired',
9821029
'objectIdRequired',
9831030
'objectRequired',
1031+
'oneOfRequired',
9841032
'stringRequired',
9851033
'createdAt',
9861034
'updatedAt',
@@ -1015,6 +1063,8 @@ describe('schema', () => {
10151063
objectIdRequired: ObjectId;
10161064
objectOptional?: { foo?: number };
10171065
objectRequired: { foo?: number };
1066+
oneOfOptional?: number | string;
1067+
oneOfRequired: number | string;
10181068
stringOptional?: string;
10191069
stringRequired: string;
10201070
createdAt: Date;

src/__tests__/types.test.ts

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -842,32 +842,33 @@ describe('types', () => {
842842
expectType<typeof value>('foo');
843843
expectType<typeof value>(undefined);
844844
});
845-
});
846845

847-
test('required', () => {
848-
const value = types.oneOf([types.boolean(), types.string()], { required: true });
846+
test('required', () => {
847+
const value = types.oneOf([types.boolean(), types.string()], { required: true });
849848

850-
expect(value).toEqual(
851-
expect.objectContaining({
852-
oneOf: [
853-
{
854-
$required: true,
855-
type: 'boolean',
856-
},
857-
{
858-
$required: true,
859-
type: 'string',
860-
},
861-
],
862-
})
863-
);
864-
expectType<boolean | string>(value);
865-
// @ts-expect-error `value` should not be `number`
866-
expectType<number>(value);
867-
// @ts-expect-error `value` should not be `undefined`
868-
expectType<undefined>(value);
869-
expectType<typeof value>(true);
870-
expectType<typeof value>('foo');
849+
expect(value).toEqual(
850+
expect.objectContaining({
851+
$required: true,
852+
oneOf: [
853+
{
854+
$required: true,
855+
type: 'boolean',
856+
},
857+
{
858+
$required: true,
859+
type: 'string',
860+
},
861+
],
862+
})
863+
);
864+
expectType<boolean | string>(value);
865+
// @ts-expect-error `value` should not be `number`
866+
expectType<number>(value);
867+
// @ts-expect-error `value` should not be `undefined`
868+
expectType<undefined>(value);
869+
expectType<typeof value>(true);
870+
expectType<typeof value>('foo');
871+
});
871872
});
872873
});
873874
});

src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ export function oneOf<Types extends any[], Options extends GenericOptions>(
205205

206206
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
207207
return {
208+
...(required ? { $required: true } : {}),
208209
oneOf: required
209210
? // eslint-disable-next-line @typescript-eslint/no-unsafe-return
210211
types.map((type) => ({

0 commit comments

Comments
 (0)