import { Simplify } from "./Simplify.mjs"; //#region src/types/Merge.d.ts /** * The result of deeply merging the source type `S` into the target type `T`, * matching what `merge(target, source)` returns at runtime. * * Keys present on only one side are kept as-is. When both sides have a plain * object at the same key, the merge recurses; tuples merge index by index, and * other arrays merge into an array of both element types. If the source value * can be `undefined`, the target type is kept because `merge` skips * `undefined` source values. Values that are not plain objects or arrays * (functions, `Date`, `RegExp`, `Map`, `Set`, etc.) are not merged into; * the source value replaces the target value. When an array meets a plain * object, `merge` keeps the target and assigns the source's properties onto * it, so both property sets are kept (`T & S`). * * @template T - Type of the target object. * @template S - Type of the source object. * * @example * type Target = { a: number; b: { x: number; y: number } }; * type Source = { b: { y: string; z: boolean }; c: string }; * type Result = Merge; * // => { a: number; b: { x: number; y: string; z: boolean }; c: string } */ type Merge = undefined extends S ? T | MergeDefined> : MergeDefined; /** * Values `merge` does not merge into: everything that is not a plain object * or an array. The source value replaces the target value instead. */ type NonMergeable = ((...args: any[]) => unknown) | Date | RegExp | Error | Promise | ReadonlyMap | ReadonlySet | WeakMap | WeakSet; type MergeDefined = S extends readonly unknown[] ? (T extends readonly unknown[] ? MergeArrays : T extends NonMergeable ? S : T extends object ? T & S : S) : S extends NonMergeable ? S : S extends object ? (T extends readonly unknown[] ? T & S : T extends NonMergeable ? S : T extends object ? MergeRecords : S) : S; type MergeArrays = T extends readonly [] ? S : S extends readonly [] ? T : T extends readonly [infer TH, ...infer TR] ? S extends readonly [infer SH, ...infer SR] ? [Merge, ...MergeArrays] : Array : Array; type MergeRecords = Simplify & Omit & { [K in keyof T & keyof S]: Merge }>; //#endregion export { Merge };