From 982665274a80bec57dd53f550c39047e3f663003 Mon Sep 17 00:00:00 2001 From: Theron Luhn Date: Thu, 6 Feb 2025 22:25:31 -0800 Subject: [PATCH 1/3] Don't remove `null` type if a default is present. --- packages/openapi-typescript/examples/github-api-next.ts | 2 +- packages/openapi-typescript/src/transform/schema-object.ts | 4 +--- .../test/transform/schema-object/string.test.ts | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/openapi-typescript/examples/github-api-next.ts b/packages/openapi-typescript/examples/github-api-next.ts index 3e54966f1..454391ea9 100644 --- a/packages/openapi-typescript/examples/github-api-next.ts +++ b/packages/openapi-typescript/examples/github-api-next.ts @@ -108750,7 +108750,7 @@ export interface operations { /** @description The name of the task for the deployment (e.g., `deploy` or `deploy:migrations`). */ task?: string; /** @description The name of the environment that was deployed to (e.g., `staging` or `production`). */ - environment?: string; + environment?: string | null; /** @description The number of results per page (max 100). For more information, see "[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api)." */ per_page?: components["parameters"]["per-page"]; /** @description The page number of the results to fetch. For more information, see "[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api)." */ diff --git a/packages/openapi-typescript/src/transform/schema-object.ts b/packages/openapi-typescript/src/transform/schema-object.ts index a41ce0e69..f9140c7f3 100644 --- a/packages/openapi-typescript/src/transform/schema-object.ts +++ b/packages/openapi-typescript/src/transform/schema-object.ts @@ -405,9 +405,7 @@ function transformSchemaObjectCore(schemaObject: SchemaObject, options: Transfor } else { for (const t of schemaObject.type) { if (t === "null" || t === null) { - if (!schemaObject.default) { - uniqueTypes.push(NULL); - } + uniqueTypes.push(NULL); } else { uniqueTypes.push(transformSchemaObject({ ...schemaObject, type: t } as SchemaObject, options)); } diff --git a/packages/openapi-typescript/test/transform/schema-object/string.test.ts b/packages/openapi-typescript/test/transform/schema-object/string.test.ts index e5e9a5ac1..12e9d5480 100644 --- a/packages/openapi-typescript/test/transform/schema-object/string.test.ts +++ b/packages/openapi-typescript/test/transform/schema-object/string.test.ts @@ -102,7 +102,7 @@ describe("transformSchemaObject > string", () => { "default + nullable", { given: { type: ["string", "null"], default: "en" }, - want: "string", + want: "string | null", }, ], [ From 1e6f967524dcd84b538b69414a61cf1a9b1053b2 Mon Sep 17 00:00:00 2001 From: Theron Luhn Date: Thu, 6 Feb 2025 22:36:02 -0800 Subject: [PATCH 2/3] Don't remove `null` type from enums if default is present. --- .../examples/github-api-export-type-immutable.ts | 4 ++-- packages/openapi-typescript/examples/github-api-immutable.ts | 4 ++-- packages/openapi-typescript/examples/github-api-required.ts | 4 ++-- .../openapi-typescript/examples/github-api-root-types.ts | 4 ++-- packages/openapi-typescript/examples/github-api.ts | 4 ++-- packages/openapi-typescript/src/transform/schema-object.ts | 5 +---- .../test/transform/schema-object/string.test.ts | 2 +- 7 files changed, 12 insertions(+), 15 deletions(-) diff --git a/packages/openapi-typescript/examples/github-api-export-type-immutable.ts b/packages/openapi-typescript/examples/github-api-export-type-immutable.ts index 699297eb3..7a331481f 100644 --- a/packages/openapi-typescript/examples/github-api-export-type-immutable.ts +++ b/packages/openapi-typescript/examples/github-api-export-type-immutable.ts @@ -32229,7 +32229,7 @@ export type components = { * @default RIGHT * @enum {string|null} */ - readonly start_side: "LEFT" | "RIGHT"; + readonly start_side: "LEFT" | "RIGHT" | null; /** * @description The line of the blob to which the comment applies. The last line of the range for a multi-line comment * @example 2 @@ -33004,7 +33004,7 @@ export type components = { * @default RIGHT * @enum {string|null} */ - readonly start_side: "LEFT" | "RIGHT"; + readonly start_side: "LEFT" | "RIGHT" | null; /** * @description The line of the blob to which the comment applies. The last line of the range for a multi-line comment * @example 2 diff --git a/packages/openapi-typescript/examples/github-api-immutable.ts b/packages/openapi-typescript/examples/github-api-immutable.ts index 25a97d3f9..11b754901 100644 --- a/packages/openapi-typescript/examples/github-api-immutable.ts +++ b/packages/openapi-typescript/examples/github-api-immutable.ts @@ -32229,7 +32229,7 @@ export interface components { * @default RIGHT * @enum {string|null} */ - readonly start_side: "LEFT" | "RIGHT"; + readonly start_side: "LEFT" | "RIGHT" | null; /** * @description The line of the blob to which the comment applies. The last line of the range for a multi-line comment * @example 2 @@ -33004,7 +33004,7 @@ export interface components { * @default RIGHT * @enum {string|null} */ - readonly start_side: "LEFT" | "RIGHT"; + readonly start_side: "LEFT" | "RIGHT" | null; /** * @description The line of the blob to which the comment applies. The last line of the range for a multi-line comment * @example 2 diff --git a/packages/openapi-typescript/examples/github-api-required.ts b/packages/openapi-typescript/examples/github-api-required.ts index ed8280c84..a65e04bb1 100644 --- a/packages/openapi-typescript/examples/github-api-required.ts +++ b/packages/openapi-typescript/examples/github-api-required.ts @@ -32229,7 +32229,7 @@ export interface components { * @default RIGHT * @enum {string|null} */ - start_side: "LEFT" | "RIGHT"; + start_side: "LEFT" | "RIGHT" | null; /** * @description The line of the blob to which the comment applies. The last line of the range for a multi-line comment * @example 2 @@ -33004,7 +33004,7 @@ export interface components { * @default RIGHT * @enum {string|null} */ - start_side: "LEFT" | "RIGHT"; + start_side: "LEFT" | "RIGHT" | null; /** * @description The line of the blob to which the comment applies. The last line of the range for a multi-line comment * @example 2 diff --git a/packages/openapi-typescript/examples/github-api-root-types.ts b/packages/openapi-typescript/examples/github-api-root-types.ts index f010442dc..246f75a25 100644 --- a/packages/openapi-typescript/examples/github-api-root-types.ts +++ b/packages/openapi-typescript/examples/github-api-root-types.ts @@ -32229,7 +32229,7 @@ export interface components { * @default RIGHT * @enum {string|null} */ - start_side: "LEFT" | "RIGHT"; + start_side: "LEFT" | "RIGHT" | null; /** * @description The line of the blob to which the comment applies. The last line of the range for a multi-line comment * @example 2 @@ -33004,7 +33004,7 @@ export interface components { * @default RIGHT * @enum {string|null} */ - start_side: "LEFT" | "RIGHT"; + start_side: "LEFT" | "RIGHT" | null; /** * @description The line of the blob to which the comment applies. The last line of the range for a multi-line comment * @example 2 diff --git a/packages/openapi-typescript/examples/github-api.ts b/packages/openapi-typescript/examples/github-api.ts index 13489f8f8..95dbc91b6 100644 --- a/packages/openapi-typescript/examples/github-api.ts +++ b/packages/openapi-typescript/examples/github-api.ts @@ -32229,7 +32229,7 @@ export interface components { * @default RIGHT * @enum {string|null} */ - start_side: "LEFT" | "RIGHT"; + start_side: "LEFT" | "RIGHT" | null; /** * @description The line of the blob to which the comment applies. The last line of the range for a multi-line comment * @example 2 @@ -33004,7 +33004,7 @@ export interface components { * @default RIGHT * @enum {string|null} */ - start_side: "LEFT" | "RIGHT"; + start_side: "LEFT" | "RIGHT" | null; /** * @description The line of the blob to which the comment applies. The last line of the range for a multi-line comment * @example 2 diff --git a/packages/openapi-typescript/src/transform/schema-object.ts b/packages/openapi-typescript/src/transform/schema-object.ts index f9140c7f3..ef49254bb 100644 --- a/packages/openapi-typescript/src/transform/schema-object.ts +++ b/packages/openapi-typescript/src/transform/schema-object.ts @@ -130,10 +130,7 @@ export function transformSchemaObjectWithComposition( return hasNull ? tsUnion([ref, NULL]) : ref; } const enumType = schemaObject.enum.map(tsLiteral); - if ( - ((Array.isArray(schemaObject.type) && schemaObject.type.includes("null")) || schemaObject.nullable) && - !schemaObject.default - ) { + if ((Array.isArray(schemaObject.type) && schemaObject.type.includes("null")) || schemaObject.nullable) { enumType.push(NULL); } diff --git a/packages/openapi-typescript/test/transform/schema-object/string.test.ts b/packages/openapi-typescript/test/transform/schema-object/string.test.ts index 12e9d5480..0b3cfa1bd 100644 --- a/packages/openapi-typescript/test/transform/schema-object/string.test.ts +++ b/packages/openapi-typescript/test/transform/schema-object/string.test.ts @@ -109,7 +109,7 @@ describe("transformSchemaObject > string", () => { "default + nullable + enum", { given: { type: ["string", "null"], enum: ["en", "es", "fr", "de"], default: "en" }, - want: '"en" | "es" | "fr" | "de"', + want: '"en" | "es" | "fr" | "de" | null', }, ], [ From 705f3e458dcc9ed598e1a1bfc7d2d2310fab0de4 Mon Sep 17 00:00:00 2001 From: Theron Luhn Date: Thu, 6 Feb 2025 22:50:24 -0800 Subject: [PATCH 3/3] Don't remove `null` type if default is present (legacy) --- packages/openapi-typescript/examples/digital-ocean-api.ts | 2 +- .../examples/github-api-export-type-immutable.ts | 2 +- packages/openapi-typescript/examples/github-api-immutable.ts | 2 +- packages/openapi-typescript/examples/github-api-required.ts | 2 +- packages/openapi-typescript/examples/github-api-root-types.ts | 2 +- packages/openapi-typescript/examples/github-api.ts | 2 +- packages/openapi-typescript/src/transform/schema-object.ts | 2 +- .../test/transform/schema-object/string.test.ts | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/openapi-typescript/examples/digital-ocean-api.ts b/packages/openapi-typescript/examples/digital-ocean-api.ts index e484f567b..c15138163 100644 --- a/packages/openapi-typescript/examples/digital-ocean-api.ts +++ b/packages/openapi-typescript/examples/digital-ocean-api.ts @@ -12326,7 +12326,7 @@ export interface components { * "web" * ] */ - tags: string[]; + tags: string[] | null; /** * @description A string containing 'user data' which may be used to configure the Droplet on first boot, often a 'cloud-config' file or Bash script. It must be plain text and may not exceed 64 KiB in size. * @example #cloud-config diff --git a/packages/openapi-typescript/examples/github-api-export-type-immutable.ts b/packages/openapi-typescript/examples/github-api-export-type-immutable.ts index 7a331481f..483598b53 100644 --- a/packages/openapi-typescript/examples/github-api-export-type-immutable.ts +++ b/packages/openapi-typescript/examples/github-api-export-type-immutable.ts @@ -108426,7 +108426,7 @@ export interface operations { /** @description The name of the task for the deployment (e.g., `deploy` or `deploy:migrations`). */ readonly task?: string; /** @description The name of the environment that was deployed to (e.g., `staging` or `production`). */ - readonly environment?: string; + readonly environment?: string | null; /** @description The number of results per page (max 100). For more information, see "[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api)." */ readonly per_page?: components["parameters"]["per-page"]; /** @description The page number of the results to fetch. For more information, see "[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api)." */ diff --git a/packages/openapi-typescript/examples/github-api-immutable.ts b/packages/openapi-typescript/examples/github-api-immutable.ts index 11b754901..323ea9428 100644 --- a/packages/openapi-typescript/examples/github-api-immutable.ts +++ b/packages/openapi-typescript/examples/github-api-immutable.ts @@ -108426,7 +108426,7 @@ export interface operations { /** @description The name of the task for the deployment (e.g., `deploy` or `deploy:migrations`). */ readonly task?: string; /** @description The name of the environment that was deployed to (e.g., `staging` or `production`). */ - readonly environment?: string; + readonly environment?: string | null; /** @description The number of results per page (max 100). For more information, see "[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api)." */ readonly per_page?: components["parameters"]["per-page"]; /** @description The page number of the results to fetch. For more information, see "[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api)." */ diff --git a/packages/openapi-typescript/examples/github-api-required.ts b/packages/openapi-typescript/examples/github-api-required.ts index a65e04bb1..ff4362624 100644 --- a/packages/openapi-typescript/examples/github-api-required.ts +++ b/packages/openapi-typescript/examples/github-api-required.ts @@ -108426,7 +108426,7 @@ export interface operations { /** @description The name of the task for the deployment (e.g., `deploy` or `deploy:migrations`). */ task?: string; /** @description The name of the environment that was deployed to (e.g., `staging` or `production`). */ - environment?: string; + environment?: string | null; /** @description The number of results per page (max 100). For more information, see "[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api)." */ per_page?: components["parameters"]["per-page"]; /** @description The page number of the results to fetch. For more information, see "[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api)." */ diff --git a/packages/openapi-typescript/examples/github-api-root-types.ts b/packages/openapi-typescript/examples/github-api-root-types.ts index 246f75a25..dd0d43544 100644 --- a/packages/openapi-typescript/examples/github-api-root-types.ts +++ b/packages/openapi-typescript/examples/github-api-root-types.ts @@ -109453,7 +109453,7 @@ export interface operations { /** @description The name of the task for the deployment (e.g., `deploy` or `deploy:migrations`). */ task?: string; /** @description The name of the environment that was deployed to (e.g., `staging` or `production`). */ - environment?: string; + environment?: string | null; /** @description The number of results per page (max 100). For more information, see "[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api)." */ per_page?: components["parameters"]["per-page"]; /** @description The page number of the results to fetch. For more information, see "[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api)." */ diff --git a/packages/openapi-typescript/examples/github-api.ts b/packages/openapi-typescript/examples/github-api.ts index 95dbc91b6..510f78b83 100644 --- a/packages/openapi-typescript/examples/github-api.ts +++ b/packages/openapi-typescript/examples/github-api.ts @@ -108426,7 +108426,7 @@ export interface operations { /** @description The name of the task for the deployment (e.g., `deploy` or `deploy:migrations`). */ task?: string; /** @description The name of the environment that was deployed to (e.g., `staging` or `production`). */ - environment?: string; + environment?: string | null; /** @description The number of results per page (max 100). For more information, see "[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api)." */ per_page?: components["parameters"]["per-page"]; /** @description The page number of the results to fetch. For more information, see "[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api)." */ diff --git a/packages/openapi-typescript/src/transform/schema-object.ts b/packages/openapi-typescript/src/transform/schema-object.ts index ef49254bb..9f0a3b2bf 100644 --- a/packages/openapi-typescript/src/transform/schema-object.ts +++ b/packages/openapi-typescript/src/transform/schema-object.ts @@ -263,7 +263,7 @@ export function transformSchemaObjectWithComposition( } } - if (finalType !== UNKNOWN && schemaObject.nullable && !schemaObject.default) { + if (finalType !== UNKNOWN && schemaObject.nullable) { finalType = tsNullable([finalType]); } diff --git a/packages/openapi-typescript/test/transform/schema-object/string.test.ts b/packages/openapi-typescript/test/transform/schema-object/string.test.ts index 0b3cfa1bd..54033d404 100644 --- a/packages/openapi-typescript/test/transform/schema-object/string.test.ts +++ b/packages/openapi-typescript/test/transform/schema-object/string.test.ts @@ -116,7 +116,7 @@ describe("transformSchemaObject > string", () => { "default + nullable (deprecated syntax)", { given: { type: "string", default: "en", nullable: true }, - want: "string", + want: "string | null", }, ], ];