import type {Merge} from 'type-fest';
type Foo = {
a: string;
b: number;
};
type Bar = {
a: number; // Conflicts with Foo['a']
c: boolean;
};
// With `&`, `a` becomes `string & number` which is `never`. Not what you want.
type WithIntersection = (Foo & Bar)['a'];
//=> never
// With `Merge`, `a` is cleanly overridden to `number`.
type WithMerge = Merge<Foo, Bar>['a'];
//=> number
import type {Merge} from 'type-fest';
type Foo = {
[x: string]: unknown;
[x: number]: unknown;
foo: string;
bar: symbol;
};
type Bar = {
[x: number]: number;
[x: symbol]: unknown;
bar: Date;
baz: boolean;
};
export type FooBar = Merge<Foo, Bar>;
//=> {
// [x: string]: unknown;
// [x: number]: number;
// [x: symbol]: unknown;
// foo: string;
// bar: Date;
// baz: boolean;
// }
Note: If you want a merge type that more accurately reflects the runtime behavior of object spread or Object.assign, refer to the ObjectMerge type.
Merge two types into a new type. Keys of the second type overrides keys of the first type.
This is different from the TypeScript
&(intersection) operator. With&, conflicting property types are intersected, which often results innever. For example,{a: string} & {a: number}makesabecomestring & number, which resolves tonever. WithMerge, the second type's keys cleanly override the first, soMerge<{a: string}, {a: number}>gives{a: number}as expected.Mergealso produces a flattened type (viaSimplify), making it more readable in IDE tooltips compared toA & B.