Skip to content

Commit 40bf33d

Browse files
committed
Fix schema objects with default + nullable
1 parent a7dbe90 commit 40bf33d

File tree

4 files changed

+50
-22
lines changed

4 files changed

+50
-22
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"devDependencies": {
1818
"@biomejs/biome": "^1.7.3",
1919
"@changesets/changelog-github": "^0.5.0",
20-
"@changesets/cli": "^2.27.1",
20+
"@changesets/cli": "^2.27.2",
2121
"del-cli": "^5.1.0",
2222
"prettier": "^3.2.5",
2323
"typescript": "^5.4.5"

packages/openapi-typescript/src/transform/schema-object.ts

+15-8
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,10 @@ export function transformSchemaObjectWithComposition(
116116
return ts.factory.createTypeReferenceNode(enumType.name);
117117
}
118118
const enumType = schemaObject.enum.map(tsLiteral);
119-
if ((Array.isArray(schemaObject.type) && schemaObject.type.includes("null")) || schemaObject.nullable) {
119+
if (
120+
((Array.isArray(schemaObject.type) && schemaObject.type.includes("null")) || schemaObject.nullable) &&
121+
!schemaObject.default
122+
) {
120123
enumType.push(NULL);
121124
}
122125

@@ -242,7 +245,7 @@ export function transformSchemaObjectWithComposition(
242245
// if final type could be generated, return intersection of all members
243246
if (finalType) {
244247
// deprecated nullable
245-
if (schemaObject.nullable) {
248+
if (schemaObject.nullable && !schemaObject.default) {
246249
return tsNullable([finalType]);
247250
}
248251
return finalType;
@@ -364,7 +367,7 @@ function transformSchemaObjectCore(schemaObject: SchemaObject, options: Transfor
364367
// polymorphic, or 3.1 nullable
365368
if (Array.isArray(schemaObject.type) && !Array.isArray(schemaObject)) {
366369
// skip any primitive types that appear in oneOf as well
367-
let uniqueTypes: ts.TypeNode[] = [];
370+
const uniqueTypes: ts.TypeNode[] = [];
368371
if (Array.isArray(schemaObject.oneOf)) {
369372
for (const t of schemaObject.type) {
370373
if (
@@ -383,11 +386,15 @@ function transformSchemaObjectCore(schemaObject: SchemaObject, options: Transfor
383386
);
384387
}
385388
} else {
386-
uniqueTypes = schemaObject.type.map((t) =>
387-
t === "null" || t === null
388-
? NULL
389-
: transformSchemaObject({ ...schemaObject, type: t } as SchemaObject, options),
390-
);
389+
for (const t of schemaObject.type) {
390+
if (t === "null" || t === null) {
391+
if (!schemaObject.default) {
392+
uniqueTypes.push(NULL);
393+
}
394+
} else {
395+
uniqueTypes.push(transformSchemaObject({ ...schemaObject, type: t } as SchemaObject, options));
396+
}
397+
}
391398
}
392399
return tsUnion(uniqueTypes);
393400
}

packages/openapi-typescript/test/transform/schema-object/string.test.ts

+21
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,27 @@ describe("transformSchemaObject > string", () => {
9191
want: '"A" | "B" | "C" | null',
9292
},
9393
],
94+
[
95+
"default + nullable",
96+
{
97+
given: { type: ["string", "null"], default: "en" },
98+
want: "string",
99+
},
100+
],
101+
[
102+
"default + nullable + enum",
103+
{
104+
given: { type: ["string", "null"], enum: ["en", "es", "fr", "de"], default: "en" },
105+
want: '"en" | "es" | "fr" | "de"',
106+
},
107+
],
108+
[
109+
"default + nullable (deprecated syntax)",
110+
{
111+
given: { type: "string", default: "en", nullable: true },
112+
want: "string",
113+
},
114+
],
94115
];
95116

96117
for (const [testName, { given, want, options = DEFAULT_OPTIONS, ci }] of tests) {

pnpm-lock.yaml

+13-13
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)