/**
 * Creates an object copy by mutating a draft Object/Array/Map/Set or any of its descendants.
 */
export declare function update<T extends object>(obj: T, updater: (draft: Draft<T>) => NoReturn): T;
export declare function clone<T extends object>(obj: T): any;
interface DraftArray<T> {
    readonly length: number;
    [n: number]: Draft<T> | undefined;
    /** Iterator */
    [Symbol.iterator](): IterableIterator<T>;
    /**
     * Returns an iterable of [key, value] pairs for every entry in the array
     */
    entries(): IterableIterator<[number, T]>;
    /**
     * Returns an iterable of keys in the array
     */
    keys(): IterableIterator<number>;
    /**
     * Returns an iterable of values in the array
     */
    values(): IterableIterator<T>;
    /**
     * Performs the specified action for each element in an array.
     * Note: This never create an object draft. Access the item by index again to mutate it.
     */
    forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void;
    indexOf(searchElement: T, fromIndex?: number): number;
    includes(searchElement: T, fromIndex?: number): boolean;
    some(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): boolean;
    findIndex(predicate: (value: T, index: number, obj: T[]) => unknown, thisArg?: any): number;
    every(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): boolean;
    map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): DraftArray<U>;
    filter(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): DraftArray<T>;
    reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T;
    reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T;
    /**
     * Adds an item at the front of the Array.
     */
    prepend(item: T): void;
    /**
     * Adds an item at the back of the Array.
     */
    append(item: T): void;
    /**
     * Inserts an item at the specified index in the Array.
     */
    insert(item: T, index: number): void;
    /**
     * Runs a predicate for each item of the Array.
     * If it returns true, a Draft item is created and  given to updateFunction, ready to be mutated.
     */
    updateIf(predicate: (item: T, index: number) => boolean, updateFunction: (item: Draft<T>, index: number) => NoReturn): void;
    /**
     * Removes all items satisfying a predicate. This is the mutating (at the draft level) equivalent of filter().
     */
    removeIf(predicate: (item: T, index: number) => boolean): void;
}
interface DraftMap<K, V> extends Omit<Map<K, V>, 'get'> {
    /** Returns an iterable of entries in the map. */
    [Symbol.iterator](): IterableIterator<[K, V]>;
    /**
     * If the key is found, returns the drafted value, else return undefined.
     */
    get(key: K): Draft<V> | undefined;
    /**
     * If the key is found, run the drafted value through an update function.
     * For primitives, the update function must return a new value whereas for objects, the drafted value can be modified directly.
     */
    updateValue(key: K, updater: (value: Draft<V>) => V extends AtomicObject ? V : NoReturn): void;
}
interface DraftSet<E> extends Set<E> {
}
/** Types that should never be drafted */
export declare type AtomicObject = Function | Promise<any> | Date | RegExp | Boolean | Number | String;
declare type IsTuple<T extends ReadonlyArray<any>> = T extends never[] ? true : T extends ReadonlyArray<infer U> ? U[] extends T ? false : true : true;
declare type WritableDraft<T> = {
    -readonly [K in keyof T]: Draft<T[K]>;
};
export declare type Draft<T> = T extends AtomicObject ? T : T extends ReadonlyMap<infer K, infer V> ? DraftMap<K, V> : T extends ReadonlySet<infer E> ? DraftSet<E> : T extends ReadonlyArray<infer E> ? IsTuple<T> extends true ? WritableDraft<T> : DraftArray<E> : T extends object ? WritableDraft<T> : T;
/**
 * Type-cast from a regular type to its draft type.
 * Use this if you want to assign a regular value wholesale instead of mutating an existing one.
 */
export declare function toDraft<T>(obj: T): Draft<T>;
export declare type NoReturn = void | undefined;
export {};
