/** * For union true: for every key in T or U, use U’s type if available; otherwise T’s. */ type Merge = { [K in keyof T | keyof U]: K extends keyof U ? U[K] : K extends keyof T ? T[K] : never; }; /** * For union false: only keys in T are retained; if U has a key, override its type. */ type MergeNonUnion = { [K in keyof T]: K extends keyof U ? U[K] : T[K]; }; /** * Recursively merge an array of source objects. * For each element in the array, apply Merge (if union is true) * or MergeNonUnion (if union is false). */ type MergeArray[], Union extends boolean> = U extends [infer Head, ...infer Tail] ? Head extends Record ? Tail extends Record[] ? MergeArray : MergeNonUnion, Tail, Union> : Union extends true ? Merge : MergeNonUnion : T : T; type Merged, U extends Record | Record[], Union extends boolean> = U extends any[] ? MergeArray : Union extends true ? Merge : MergeNonUnion; /** * Deep merge two objects together while ensuring nested objects also get merged, * take note: this does not merge onto passed objects by reference but instead * returns a new object * * @param {Record} target - Base Object * @param {Record|Record[]} source - (default={}) Object to merge onto base object */ declare function merge, U extends Record | [Record, ...Record[]], Union extends boolean = false>(target: T, source: U, opts?: { /** * Defaults to false, when passed as true it ensures all keys from both objects * are available in the merged object */ union?: Union; }): Merged; export { merge, merge as default };