Skip to content

Commit fa55f48

Browse files
authored
Merge: Fix behavior with unions (#1327)
1 parent 8df92e4 commit fa55f48

File tree

2 files changed

+32
-6
lines changed

2 files changed

+32
-6
lines changed

source/merge.d.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ import type {PickIndexSignature} from './pick-index-signature.d.ts';
33
import type {Simplify} from './simplify.d.ts';
44

55
// Merges two objects without worrying about index signatures.
6-
type SimpleMerge<Destination, Source> = {
6+
type SimpleMerge<Destination, Source> = Simplify<{
77
[Key in keyof Destination as Key extends keyof Source ? never : Key]: Destination[Key];
8-
} & Source;
8+
} & Source>;
99

1010
/**
1111
Merge two types into a new type. Keys of the second type overrides keys of the first type.
@@ -45,9 +45,13 @@ Note: If you want a merge type that more accurately reflects the runtime behavio
4545
@category Object
4646
*/
4747
export type Merge<Destination, Source> =
48-
Simplify<
49-
SimpleMerge<PickIndexSignature<Destination>, PickIndexSignature<Source>>
50-
& SimpleMerge<OmitIndexSignature<Destination>, OmitIndexSignature<Source>>
51-
>;
48+
Destination extends unknown // For distributing `Destination`
49+
? Source extends unknown // For distributing `Source`
50+
? Simplify<
51+
SimpleMerge<PickIndexSignature<Destination>, PickIndexSignature<Source>>
52+
& SimpleMerge<OmitIndexSignature<Destination>, OmitIndexSignature<Source>>
53+
>
54+
: never // Should never happen
55+
: never; // Should never happen
5256

5357
export {};

test-d/merge.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,3 +165,25 @@ expectType<{
165165
t4?: number;
166166
list: string[];
167167
}>(baz);
168+
169+
// Unions
170+
expectType<{foo: number} | {foo: string; bar: boolean}>(
171+
{} as Merge<{foo: string}, {foo: number} | {bar: boolean}>,
172+
);
173+
expectType<{foo: string} | {bar: boolean; foo: string}>(
174+
{} as Merge<{foo: number} | {bar: boolean}, {foo: string}>,
175+
);
176+
expectType<{foo: number} | {foo: string; baz: boolean} | {bar: number; foo: number} | {bar: number; baz: boolean}>(
177+
{} as Merge<{foo: string} | {bar: number}, {foo: number} | {baz: boolean}>,
178+
);
179+
expectType<
180+
| {[x: number]: number; foo: number; bar: string}
181+
| {[x: number]: number; bar: bigint; foo: number}
182+
| {foo: string; bar: boolean; baz: boolean}
183+
| {[x: number]: bigint; bar: boolean; baz: boolean}
184+
>(
185+
{} as Merge<
186+
{foo: string; bar: string} | {[x: number]: bigint; bar: bigint},
187+
{[x: number]: number; foo: number} | {bar: boolean; baz: boolean}
188+
>,
189+
);

0 commit comments

Comments
 (0)