From 9302f947bda64c8bc082609b5b3d5f7a3c29743c Mon Sep 17 00:00:00 2001 From: Gary Schwartzbard Date: Thu, 14 Nov 2024 13:42:21 -0500 Subject: [PATCH 1/2] fix: prevent infinite recursion with NoUndefined and RecursiveRequired re: DocumentType --- .changeset/three-trainers-know.md | 5 +++ .../types/src/transform/no-undefined.spec.ts | 40 +++++++++++++------ packages/types/src/transform/no-undefined.ts | 7 +++- 3 files changed, 39 insertions(+), 13 deletions(-) create mode 100644 .changeset/three-trainers-know.md diff --git a/.changeset/three-trainers-know.md b/.changeset/three-trainers-know.md new file mode 100644 index 00000000000..0d906e51b85 --- /dev/null +++ b/.changeset/three-trainers-know.md @@ -0,0 +1,5 @@ +--- +"@smithy/types": patch +--- + +prevent infinite recursion with NoUndefined and RecursiveRequired re: DocumentType diff --git a/packages/types/src/transform/no-undefined.spec.ts b/packages/types/src/transform/no-undefined.spec.ts index 3ee15f4c56d..a7dfe22b2b4 100644 --- a/packages/types/src/transform/no-undefined.spec.ts +++ b/packages/types/src/transform/no-undefined.spec.ts @@ -3,6 +3,7 @@ import type { Client } from "../client"; import { CommandIO } from "../command"; import type { HttpHandlerOptions } from "../http"; import type { MetadataBearer } from "../response"; +import { DocumentType } from "../shapes"; import type { Exact } from "./exact"; import type { AssertiveClient, NoUndefined, UncheckedClient } from "./no-undefined"; @@ -13,6 +14,7 @@ type A = { required: string | undefined; optional?: string; nested: A; + document: DocumentType; }; { @@ -22,6 +24,8 @@ type A = { const assert1: Exact = true as const; const assert2: Exact = true as const; const assert3: Exact = true as const; + const assert4: Exact = true as const; + const assert5: Exact = true as const; } { @@ -30,6 +34,7 @@ type A = { b: number | undefined; c: string | number | undefined; optional?: string; + document: DocumentType | undefined; }; type MyOutput = { @@ -37,6 +42,7 @@ type A = { b?: number; c?: string | number; r?: MyOutput; + document?: DocumentType; } & MetadataBearer; type MyConfig = { @@ -66,6 +72,7 @@ type A = { a: "", b: 0, c: 0, + document: { aa: "b" }, }; const get = c.getObject(input); const output = null as unknown as Awaited; @@ -73,10 +80,12 @@ type A = { const assert1: Exact = true as const; const assert2: Exact = true as const; const assert3: Exact = true as const; + const assert4: Exact = true as const; if (output.r) { - const assert4: Exact = true as const; - const assert5: Exact = true as const; - const assert6: Exact = true as const; + const assert5: Exact = true as const; + const assert6: Exact = true as const; + const assert7: Exact = true as const; + const assert8: Exact = true as const; } } @@ -88,6 +97,7 @@ type A = { a: "", b: 0, c: 0, + document: { aa: "b" }, }; const get = c.getObject(input); const output = null as unknown as Awaited; @@ -95,9 +105,11 @@ type A = { const assert1: Exact = true as const; const assert2: Exact = true as const; const assert3: Exact = true as const; - const assert4: Exact = true as const; - const assert5: Exact = true as const; - const assert6: Exact = true as const; + const assert4: Exact = true as const; + const assert5: Exact = true as const; + const assert6: Exact = true as const; + const assert7: Exact = true as const; + const assert8: Exact = true as const; } { @@ -109,10 +121,12 @@ type A = { const assert1: Exact = true as const; const assert2: Exact = true as const; const assert3: Exact = true as const; + const assert4: Exact = true as const; if (output.r) { - const assert4: Exact = true as const; - const assert5: Exact = true as const; - const assert6: Exact = true as const; + const assert5: Exact = true as const; + const assert6: Exact = true as const; + const assert7: Exact = true as const; + const assert8: Exact = true as const; } } @@ -125,10 +139,12 @@ type A = { const assert1: Exact = true as const; const assert2: Exact = true as const; const assert3: Exact = true as const; + const assert4: Exact = true as const; if (output.r) { - const assert4: Exact = true as const; - const assert5: Exact = true as const; - const assert6: Exact = true as const; + const assert5: Exact = true as const; + const assert6: Exact = true as const; + const assert7: Exact = true as const; + const assert8: Exact = true as const; } } } diff --git a/packages/types/src/transform/no-undefined.ts b/packages/types/src/transform/no-undefined.ts index 2dfb6b495fb..bb7671ab004 100644 --- a/packages/types/src/transform/no-undefined.ts +++ b/packages/types/src/transform/no-undefined.ts @@ -1,5 +1,6 @@ import type { InvokeMethod, InvokeMethodOptionalArgs } from "../client"; import type { GetOutputType } from "../command"; +import type { DocumentType } from "../shapes" /** * @public @@ -33,7 +34,9 @@ export type UncheckedClient = UncheckedClientOutputTypes< * Excludes undefined recursively. */ export type NoUndefined = T extends Function - ? T + ? T + : T extends DocumentType + ? T : [T] extends [object] ? { [key in keyof T]: NoUndefined; @@ -46,6 +49,8 @@ export type NoUndefined = T extends Function * Excludes undefined and optional recursively. */ export type RecursiveRequired = T extends Function + ? T + : T extends DocumentType ? T : [T] extends [object] ? { From 71c24de1a954edd4ea6328e36d4c30de5c4d92ed Mon Sep 17 00:00:00 2001 From: George Fu Date: Thu, 14 Nov 2024 18:46:16 +0000 Subject: [PATCH 2/2] formatting --- packages/types/src/transform/no-undefined.ts | 28 ++++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/packages/types/src/transform/no-undefined.ts b/packages/types/src/transform/no-undefined.ts index bb7671ab004..cd35d764512 100644 --- a/packages/types/src/transform/no-undefined.ts +++ b/packages/types/src/transform/no-undefined.ts @@ -1,6 +1,6 @@ import type { InvokeMethod, InvokeMethodOptionalArgs } from "../client"; import type { GetOutputType } from "../command"; -import type { DocumentType } from "../shapes" +import type { DocumentType } from "../shapes"; /** * @public @@ -34,14 +34,14 @@ export type UncheckedClient = UncheckedClientOutputTypes< * Excludes undefined recursively. */ export type NoUndefined = T extends Function - ? T + ? T : T extends DocumentType - ? T - : [T] extends [object] - ? { - [key in keyof T]: NoUndefined; - } - : Exclude; + ? T + : [T] extends [object] + ? { + [key in keyof T]: NoUndefined; + } + : Exclude; /** * @internal @@ -51,12 +51,12 @@ export type NoUndefined = T extends Function export type RecursiveRequired = T extends Function ? T : T extends DocumentType - ? T - : [T] extends [object] - ? { - [key in keyof T]-?: RecursiveRequired; - } - : Exclude; + ? T + : [T] extends [object] + ? { + [key in keyof T]-?: RecursiveRequired; + } + : Exclude; /** * @internal