import { Mutable as Mutable_, OptionalKeys, Primitive, RequiredKeys } from "./types";
/**
 * Recursively merges `A` and `B`. If a property in `A` and `B` is of a
 * different type (i.e. it's not an array, Set, Map, or plain object in both,
 * the value from `B` will be used in the result).
 *
 * If there are self-references in the cloned values, array / Set items, or Map
 * keys or values, they will also be self-referencing in the result.
 */
declare const merge: <A, B>(a: A, b: B) => Merge<A, B>;
export default merge;
export declare type Merge<A, B> = A extends Primitive ? Mutable<B> : Merge_<Mutable<A>, Mutable<B>>;
declare type Merge_<A, B> = Extract<B, Primitive> | MergeList<A, B> | MergeSet<A, B> | MergeMap<A, B> | MergeObject<A, B>;
declare type MergeSet<A, B> = B extends Set<infer IB> ? (A extends Set<infer IA> ? Set<IA | IB> : B) : never;
declare type MergeMap<A, B> = B extends Map<infer KB, infer VB> ? (A extends Map<infer KA, infer VA> ? Map<KA | KB, VA | VB> : B) : never;
declare type MergeObject<A, B> = B extends Record<any, unknown> ? (A extends Record<any, unknown> ? MergeObject_<A, B> : never) : never;
declare type MergeObject_<A, B> = MakeOptional<{
    [K in keyof A | keyof B]: K extends keyof B ? (K extends keyof A ? (Merge<A[K], B[K]> | (K extends OptionalKeys<B> ? A[K] : never)) : B[K]) : K extends keyof A ? A[K] : never;
}, Exclude<OptionalKeys<B>, RequiredKeys<A>> | Exclude<OptionalKeys<A>, RequiredKeys<B>>>;
declare type MergeList<A, B> = A extends unknown[] ? (B extends unknown[] ? (B[number][] extends Required<B> ? MergeArray<A, B> : A[number][] extends Required<A> ? MergeArray<A, B> : MergeTuple<A, B>) : never) : never;
declare type MergeTuple<A extends unknown[], B extends unknown[]> = B extends [
    infer H,
    ...infer T
] ? MergeTuple<[...A, H], T> : A;
declare type MergeArray<A extends unknown[], B extends unknown[]> = (A[number] | B[number])[];
declare type MakeOptional<T, O extends keyof T> = FlattenIntersection<Pick<T, Exclude<keyof T, O>> & {
    [K in O]?: T[K];
}>;
declare type FlattenIntersection<T> = {
    [K in keyof T]: T[K];
};
declare type Mutable<T> = T extends Set<any> | Map<any, any> ? T : Mutable_<T>;
