Skip to content

Commit fcd5ca8

Browse files
gschwartkuhe
andauthored
fix: prevent infinite recursion with NoUndefined and RecursiveRequired re: DocumentType (#1455)
* fix: prevent infinite recursion with NoUndefined and RecursiveRequired re: DocumentType * formatting --------- Co-authored-by: George Fu <[email protected]>
1 parent 012775c commit fcd5ca8

File tree

3 files changed

+48
-22
lines changed

3 files changed

+48
-22
lines changed

.changeset/three-trainers-know.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@smithy/types": patch
3+
---
4+
5+
prevent infinite recursion with NoUndefined and RecursiveRequired re: DocumentType

packages/types/src/transform/no-undefined.spec.ts

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type { Client } from "../client";
33
import { CommandIO } from "../command";
44
import type { HttpHandlerOptions } from "../http";
55
import type { MetadataBearer } from "../response";
6+
import { DocumentType } from "../shapes";
67
import type { Exact } from "./exact";
78
import type { AssertiveClient, NoUndefined, UncheckedClient } from "./no-undefined";
89

@@ -13,6 +14,7 @@ type A = {
1314
required: string | undefined;
1415
optional?: string;
1516
nested: A;
17+
document: DocumentType;
1618
};
1719

1820
{
@@ -22,6 +24,8 @@ type A = {
2224
const assert1: Exact<T["required"], string> = true as const;
2325
const assert2: Exact<T["nested"]["required"], string> = true as const;
2426
const assert3: Exact<T["nested"]["nested"]["required"], string> = true as const;
27+
const assert4: Exact<T["document"], DocumentType> = true as const;
28+
const assert5: Exact<T["nested"]["document"], DocumentType> = true as const;
2529
}
2630

2731
{
@@ -30,13 +34,15 @@ type A = {
3034
b: number | undefined;
3135
c: string | number | undefined;
3236
optional?: string;
37+
document: DocumentType | undefined;
3338
};
3439

3540
type MyOutput = {
3641
a?: string;
3742
b?: number;
3843
c?: string | number;
3944
r?: MyOutput;
45+
document?: DocumentType;
4046
} & MetadataBearer;
4147

4248
type MyConfig = {
@@ -66,17 +72,20 @@ type A = {
6672
a: "",
6773
b: 0,
6874
c: 0,
75+
document: { aa: "b" },
6976
};
7077
const get = c.getObject(input);
7178
const output = null as unknown as Awaited<typeof get>;
7279

7380
const assert1: Exact<typeof output.a, string | undefined> = true as const;
7481
const assert2: Exact<typeof output.b, number | undefined> = true as const;
7582
const assert3: Exact<typeof output.c, string | number | undefined> = true as const;
83+
const assert4: Exact<typeof output.document, DocumentType | undefined> = true as const;
7684
if (output.r) {
77-
const assert4: Exact<typeof output.r.a, string | undefined> = true as const;
78-
const assert5: Exact<typeof output.r.b, number | undefined> = true as const;
79-
const assert6: Exact<typeof output.r.c, string | number | undefined> = true as const;
85+
const assert5: Exact<typeof output.r.a, string | undefined> = true as const;
86+
const assert6: Exact<typeof output.r.b, number | undefined> = true as const;
87+
const assert7: Exact<typeof output.r.c, string | number | undefined> = true as const;
88+
const assert8: Exact<typeof output.r.document, DocumentType | undefined> = true as const;
8089
}
8190
}
8291

@@ -88,16 +97,19 @@ type A = {
8897
a: "",
8998
b: 0,
9099
c: 0,
100+
document: { aa: "b" },
91101
};
92102
const get = c.getObject(input);
93103
const output = null as unknown as Awaited<typeof get>;
94104

95105
const assert1: Exact<typeof output.a, string> = true as const;
96106
const assert2: Exact<typeof output.b, number> = true as const;
97107
const assert3: Exact<typeof output.c, string | number> = true as const;
98-
const assert4: Exact<typeof output.r.a, string> = true as const;
99-
const assert5: Exact<typeof output.r.b, number> = true as const;
100-
const assert6: Exact<typeof output.r.c, string | number> = true as const;
108+
const assert4: Exact<typeof output.document, DocumentType> = true as const;
109+
const assert5: Exact<typeof output.r.a, string> = true as const;
110+
const assert6: Exact<typeof output.r.b, number> = true as const;
111+
const assert7: Exact<typeof output.r.c, string | number> = true as const;
112+
const assert8: Exact<typeof output.r.document, DocumentType> = true as const;
101113
}
102114

103115
{
@@ -109,10 +121,12 @@ type A = {
109121
const assert1: Exact<typeof output.a, string | undefined> = true as const;
110122
const assert2: Exact<typeof output.b, number | undefined> = true as const;
111123
const assert3: Exact<typeof output.c, string | number | undefined> = true as const;
124+
const assert4: Exact<typeof output.document, DocumentType | undefined> = true as const;
112125
if (output.r) {
113-
const assert4: Exact<typeof output.r.a, string | undefined> = true as const;
114-
const assert5: Exact<typeof output.r.b, number | undefined> = true as const;
115-
const assert6: Exact<typeof output.r.c, string | number | undefined> = true as const;
126+
const assert5: Exact<typeof output.r.a, string | undefined> = true as const;
127+
const assert6: Exact<typeof output.r.b, number | undefined> = true as const;
128+
const assert7: Exact<typeof output.r.c, string | number | undefined> = true as const;
129+
const assert8: Exact<typeof output.r.document, DocumentType | undefined> = true as const;
116130
}
117131
}
118132

@@ -125,10 +139,12 @@ type A = {
125139
const assert1: Exact<typeof output.a, string | undefined> = true as const;
126140
const assert2: Exact<typeof output.b, number | undefined> = true as const;
127141
const assert3: Exact<typeof output.c, string | number | undefined> = true as const;
142+
const assert4: Exact<typeof output.document, DocumentType | undefined> = true as const;
128143
if (output.r) {
129-
const assert4: Exact<typeof output.r.a, string | undefined> = true as const;
130-
const assert5: Exact<typeof output.r.b, number | undefined> = true as const;
131-
const assert6: Exact<typeof output.r.c, string | number | undefined> = true as const;
144+
const assert5: Exact<typeof output.r.a, string | undefined> = true as const;
145+
const assert6: Exact<typeof output.r.b, number | undefined> = true as const;
146+
const assert7: Exact<typeof output.r.c, string | number | undefined> = true as const;
147+
const assert8: Exact<typeof output.r.document, DocumentType | undefined> = true as const;
132148
}
133149
}
134150
}

packages/types/src/transform/no-undefined.ts

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { InvokeMethod, InvokeMethodOptionalArgs } from "../client";
22
import type { GetOutputType } from "../command";
3+
import type { DocumentType } from "../shapes";
34

45
/**
56
* @public
@@ -34,11 +35,13 @@ export type UncheckedClient<Client extends object> = UncheckedClientOutputTypes<
3435
*/
3536
export type NoUndefined<T> = T extends Function
3637
? T
37-
: [T] extends [object]
38-
? {
39-
[key in keyof T]: NoUndefined<T[key]>;
40-
}
41-
: Exclude<T, undefined>;
38+
: T extends DocumentType
39+
? T
40+
: [T] extends [object]
41+
? {
42+
[key in keyof T]: NoUndefined<T[key]>;
43+
}
44+
: Exclude<T, undefined>;
4245

4346
/**
4447
* @internal
@@ -47,11 +50,13 @@ export type NoUndefined<T> = T extends Function
4750
*/
4851
export type RecursiveRequired<T> = T extends Function
4952
? T
50-
: [T] extends [object]
51-
? {
52-
[key in keyof T]-?: RecursiveRequired<T[key]>;
53-
}
54-
: Exclude<T, undefined>;
53+
: T extends DocumentType
54+
? T
55+
: [T] extends [object]
56+
? {
57+
[key in keyof T]-?: RecursiveRequired<T[key]>;
58+
}
59+
: Exclude<T, undefined>;
5560

5661
/**
5762
* @internal

0 commit comments

Comments
 (0)