Skip to content

Commit 8873d16

Browse files
edbznvmasek
authored andcommitted
fix: handle property x-nullable
1 parent 62df466 commit 8873d16

File tree

2 files changed

+28
-14
lines changed

2 files changed

+28
-14
lines changed

src/helper.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,16 @@ export function accessProp(name: string): string {
8989
export function guardOptional(
9090
name: string,
9191
isRequired: boolean | undefined,
92+
nullable: boolean | undefined,
9293
guard: (name: string) => string,
9394
): string {
94-
return isRequired
95-
? guard(name)
96-
: `( typeof ${name} === 'undefined' || ${guard(name)} )`;
95+
const guards = [
96+
...(isRequired ? [`typeof ${name} === 'undefined'`] : []),
97+
...(nullable ? [`${name} === null`] : []),
98+
guard(name),
99+
];
100+
101+
return guards.length > 1 ? `( ${guards.join(' || ')} )` : guards.join('');
97102
}
98103

99104
export function guardDictionary(

src/parser.ts

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -361,11 +361,20 @@ function parseInterfaceProperties(
361361
: [];
362362

363363
const isRequired = requiredProps.includes(propName);
364-
364+
const nullable = propSchema['x-nullable'] || false;
365365
const parsedSchema = parseSchema(propSchema, {
366366
name: name === ADDITIONAL_PROPERTIES_KEY ? 'value' : accessProp(name),
367367
isRequired,
368+
nullable,
368369
});
370+
const parsedType = propertyAllOf.length
371+
? propertyAllOf
372+
.map(({ type }) => type)
373+
.filter((type): type is string => !!type)
374+
.join(' & ')
375+
: nullable
376+
? `${parsedSchema.type} | null`
377+
: parsedSchema.type;
369378

370379
const property: Property = {
371380
parsedSchema,
@@ -384,12 +393,7 @@ function parseInterfaceProperties(
384393
.join('\n'),
385394
2,
386395
),
387-
type: propertyAllOf.length
388-
? propertyAllOf
389-
.map(({ type }) => type)
390-
.filter((type): type is string => !!type)
391-
.join(' & ')
392-
: parsedSchema.type,
396+
type: parsedType,
393397
imports: propertyAllOf.reduce(
394398
(allImports, { imports }) => [...imports, ...allImports],
395399
parsedSchema.imports,
@@ -402,6 +406,7 @@ function parseInterfaceProperties(
402406
? guardOptional(
403407
accessProp(name),
404408
false,
409+
nullable,
405410
() =>
406411
`( ${propertyAllOf
407412
.map(({ guard }) => guard?.('this can be anything'))
@@ -427,8 +432,9 @@ function parseSchema(
427432
{
428433
name,
429434
isRequired,
435+
nullable,
430436
prefixGuards,
431-
}: ParseSchemaMetadata & { prefixGuards?: boolean },
437+
}: ParseSchemaMetadata & { prefixGuards?: boolean; nullable?: boolean },
432438
): ParsedSchema {
433439
if (Array.isArray(property.items)) {
434440
logWarn('Arrays with type diversity are currently not supported');
@@ -450,6 +456,7 @@ function parseSchema(
450456
guardOptional(
451457
name,
452458
isRequired,
459+
nullable,
453460
(iterName: string) =>
454461
`[${enumValues.join(', ')}].includes(${iterName})`,
455462
),
@@ -466,6 +473,7 @@ function parseSchema(
466473
guardOptional(
467474
name,
468475
isRequired,
476+
nullable,
469477
(iterName: string) => `typeof ${iterName} === 'object'`,
470478
),
471479
}; // type occurrence of inlined properties as object instead of any (TODO: consider supporting inlined properties)
@@ -483,6 +491,7 @@ function parseSchema(
483491
guardOptional(
484492
name,
485493
isRequired,
494+
nullable,
486495
(iterName: string) =>
487496
`${prefixGuards ? 'guards.' : ''}is${refType}(${iterName})`,
488497
),
@@ -503,7 +512,7 @@ function parseSchema(
503512
global.GLOBAL_OPTIONS.skipGuards || !parsedArrayItemsSchema.guard
504513
? undefined
505514
: () =>
506-
guardOptional(name, isRequired, (iterName: string) =>
515+
guardOptional(name, isRequired, nullable, (iterName: string) =>
507516
guardArray(iterName, parsedArrayItemsSchema.guard!),
508517
),
509518
};
@@ -526,7 +535,7 @@ function parseSchema(
526535
global.GLOBAL_OPTIONS.skipGuards || !parsedDictionarySchema.guard
527536
? undefined
528537
: () =>
529-
guardOptional(name, isRequired, (iterName: string) =>
538+
guardOptional(name, isRequired, nullable, (iterName: string) =>
530539
isJustObject
531540
? `typeof ${iterName} === 'object'`
532541
: guardDictionary(iterName, parsedDictionarySchema.guard!),
@@ -545,7 +554,7 @@ function parseSchema(
545554
: () =>
546555
type === 'any'
547556
? ''
548-
: guardOptional(name, isRequired, (iterName: string) =>
557+
: guardOptional(name, isRequired, nullable, (iterName: string) =>
549558
type === 'File'
550559
? `${iterName} instanceof File`
551560
: `typeof ${iterName} === '${type}'`,

0 commit comments

Comments
 (0)