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..cd35d764512 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 @@ -34,11 +35,13 @@ export type UncheckedClient = UncheckedClientOutputTypes< */ export type NoUndefined = T extends Function ? T - : [T] extends [object] - ? { - [key in keyof T]: NoUndefined; - } - : Exclude; + : T extends DocumentType + ? T + : [T] extends [object] + ? { + [key in keyof T]: NoUndefined; + } + : Exclude; /** * @internal @@ -47,11 +50,13 @@ export type NoUndefined = T extends Function */ export type RecursiveRequired = T extends Function ? T - : [T] extends [object] - ? { - [key in keyof T]-?: RecursiveRequired; - } - : Exclude; + : T extends DocumentType + ? T + : [T] extends [object] + ? { + [key in keyof T]-?: RecursiveRequired; + } + : Exclude; /** * @internal