Skip to content

Commit 4b49b93

Browse files
authored
SharedUnionFieldsDeep: Fix support for optional fields (#988)
1 parent 196051f commit 4b49b93

File tree

2 files changed

+17
-1
lines changed

2 files changed

+17
-1
lines changed

source/shared-union-fields-deep.d.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,13 +98,18 @@ export type SharedUnionFieldsDeep<Union, Options extends SharedUnionFieldsDeepOp
9898
Same as `SharedUnionFieldsDeep`, but accepts only `object`s and as inputs. Internal helper for `SharedUnionFieldsDeep`.
9999
*/
100100
type SharedObjectUnionFieldsDeep<Union, Options extends SharedUnionFieldsDeepOptions> =
101+
// `keyof Union` can extract the same key in union type, if there is no same key, return never.
101102
keyof Union extends infer Keys
102103
? IsNever<Keys> extends false
103104
? {
104105
[Key in keyof Union]:
105106
Union[Key] extends NonRecursiveType
106107
? Union[Key]
107-
: SharedUnionFieldsDeep<Union[Key], Options>
108+
// Remove `undefined` from the union to support optional
109+
// fields, then recover `undefined` if union was already undefined.
110+
: SharedUnionFieldsDeep<Exclude<Union[Key], undefined>, Options> | (
111+
undefined extends Required<Union>[Key] ? undefined : never
112+
)
108113
}
109114
: {}
110115
: Union;

test-d/shared-union-fields-deep.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,3 +132,14 @@ expectType<TestingType>(same);
132132
// Test for propagation with non union root object
133133
declare const nonUnionRootType: SharedUnionFieldsDeep<{union: {number: number; boolean: boolean} | {number: number}}>;
134134
expectType<{union: {number: number}}>(nonUnionRootType);
135+
136+
declare const unionWithUndefined: SharedUnionFieldsDeep<{
137+
a?: {a: string; foo: number} | {a: string; bar: string} | undefined;
138+
b?: {a: string; foo: number} | {a: string; bar: string};
139+
c: {a: string; foo: number} | {a: string; bar: string} | undefined;
140+
}>;
141+
expectType<{
142+
a?: {a: string} | undefined;
143+
b?: {a: string};
144+
c: {a: string} | undefined;
145+
}>(unionWithUndefined);

0 commit comments

Comments
 (0)