import type { ImmutableArray } from "./array.js";
import type { ImmutableObject } from "./object.js";
type MergeRecursor = (left: unknown, right: unknown) => unknown;
/**
 * Exact merge two unknown values.
 * - Always returns `right`.
 */
export declare function exactMerge(_left: unknown, right: unknown): unknown;
/**
 * Shallow merge two unknown values.
 *
 * - Two objects: props are merged together (shallowly).
 * - Two arrays: unique items are merged together (shallowly).
 * - Any other value: right value is returned.
 *
 * @returns Merged value.
 * - Will be `left` instance if no properties/items changed.
 * - Will be merged instance otherwise.
 */
export declare function shallowMerge<L extends ImmutableObject, R extends ImmutableObject>(left: L, right: R): L & R;
export declare function shallowMerge<L, R>(left: ImmutableArray<L>, right: ImmutableArray<R>): ImmutableArray<L | R>;
export declare function shallowMerge<R>(left: unknown, right: R): R;
/**
 * Deeply merge two unknown values.
 *
 * - Two objects: props are merged together (deeply).
 * - Two arrays: unique items are merged together (shallowly — arrays have no way to deep merge because array keys are not stable).
 * - Any other value: right value is returned.
 *
 * @returns Merged value.
 * - Will be `left` instance if no properties/items changed.
 * - Will be a new merged instance otherwise.
 */
export declare function deepMerge<L extends ImmutableObject, R extends ImmutableObject>(left: L, right: R): L & R;
export declare function deepMerge<L, R>(left: ImmutableArray<L>, right: ImmutableArray<R>): ImmutableArray<L | R>;
export declare function deepMerge<R>(left: unknown, right: R): R;
/**
 * Merge two arrays.
 * - Values are considered unique so values will not appear twice.
 * - Arrays have no concept of `deep merge` because array keys are not stable.
 * - Use an map/object data structure instead for values that need to be deeply mergeable (only use arrays for primitive values).
 *
 * @returns Merged array.
 * - Values that appear in both arrays will not be added twice.
 * - Will be `left` instance if no items were added.
 * - Will be a new merged array otherwise.
 */
export declare function mergeArray<L, R>(left: ImmutableArray<L>, right: ImmutableArray<R> | ImmutableArray<L>): ImmutableArray<L | R>;
/**
 * Merge two data objects.
 *
 * Properties that exist in `right` will replace or be deeply merged with properties in `left`.
 * - Only works on enumerable own keys (as returned by `Object.keys()`).
 * - Always returns a new object (or the `left` object if no changes were made).
 * - Resulting object is `cleaned`, i.e. properties in `left` or `right` that are `undefined` will be removed from the merged object.
 *
 * @param recursor Function that merges each property of the object.
 * - Defaults to `exactMerge()` to just swap the property for a newer one if it exists.
 * - Use `deepMerge()` as the recursor to merge objects deeply.
 *
 * @return Merged object.
 * - Returned instances will be the same if no changes were made.
 * - Will be `left` instance if no properties changed.
 * - Will be a new merged object otherwise.
 */
export declare function mergeObject<L extends ImmutableObject, R extends ImmutableObject>(left: L, right: R, recursor?: MergeRecursor): L & R;
export {};
