interface Disposable {
    /** Release any memory that would otherwise leak */
    dispose: () => void;
}
declare type Falsy = false | null | undefined;

/** For accessing the proxied state */
declare const $$: unique symbol;
/** For storing observers and the observable proxy */
declare const $O: unique symbol;
/** For injecting custom proxy traps */
declare const $T: unique symbol;

/** Watch the properties of the given observable object */
declare const shallowChanges: (target: ObserverTarget, onChange: (change: Change) => void) => ChangeObserver;
/** A function that can subscribe to observable objects. */
declare abstract class Observer implements Disposable {
    observed: ReadonlySet<ObservedSlot>;
    onChange: ((change: Change) => void) | null;
    /** The current nonce of our observed values combined */
    get nonce(): number;
    dispose(): void;
}
/** @internal */
declare class Observable<T extends object = any> extends Map<ObservedKey, ObservedSlot> {
    readonly source?: T | undefined;
    readonly proxy: T | undefined;
    constructor(source?: T | undefined);
    /** Return true if at least one observer exists for the given key. */
    has(key: ObservedKey): boolean;
    /** Return a `Set` of observers for the given key, even if not observed. */
    get(key: ObservedKey): ObservedSlot;
    /** Create an observer for the given key. */
    observe(key: ObservedKey, onChange: (change: Change) => void): ChangeObserver;
}
/** Mutable state with an associated observable */
declare type ObserverTarget = object & {
    [$O]?: Observable;
};
/** Any value acting as an object key */
declare type ObservedKey = any;
/** An observer set with metadata about what's being observed */
declare class ObservedSlot extends Set<ChangeObserver> {
    readonly owner: Observable;
    readonly key: ObservedKey;
    nonce: number;
    constructor(owner: Observable, key: ObservedKey);
    onChange(change: Change): void;
}
/** An observed mutation of an observable object. */
interface Change<T = any> {
    op: 'add' | 'replace' | 'remove' | 'splice' | 'clear' | 'define';
    target: object;
    key?: any;
    value?: T;
    oldValue?: T;
}
/** The most basic observer of changes. */
interface ChangeObserver extends Disposable {
    onChange: ((change: Change) => void) | null;
}

/** Run an effect when its tracked values change. */
declare function auto(effect: () => void, config?: AutoConfig): Auto;
interface AutoConfig {
    /** When true, react to changes immediately. By default, changes are delayed until the next microtask loop */
    sync?: boolean;
    /** By default, rerun the last effect (after any delay) */
    onDirty?: Auto['onDirty'];
    /** By default, errors are rethrown */
    onError?: Auto['onError'];
    /** Run an effect after an `observer` is activated */
    onCommit?: Auto['onCommit'];
    /** Run an effect after being disposed */
    onDispose?: Auto['onDispose'];
}
declare class Auto {
    sync: boolean;
    dirty: boolean;
    nonce: number;
    observer: AutoObserver | null;
    onDirty: (this: Auto) => void;
    onError: (this: Auto, error: Error) => void;
    onCommit: (observer: AutoObserver) => void;
    onDispose: () => void;
    constructor(config?: AutoConfig);
    run<T extends Function>(compute: T): any;
    /** Rerun the last effect and commit its observer */
    rerun(): any;
    /**
     * Replace the current `observer`.
     *
     * Pass a nonce to bail out if observed values have since changed.
     */
    commit(observer: AutoObserver, nonce?: number): boolean;
    dispose(): void;
    /**
     * @internal
     * Create an observer and start observing.
     *
     * The given `effect` is used by `rerun` calls made after
     * the new observer is committed.
     */
    start(effect: Function): AutoObserver;
    /**
     * @internal
     * Stop observing and reset the `dirty` flag.
     */
    stop(): this;
    /**
     * @internal
     * Replace the current `observer` when appropriate.
     */
    clear(): void;
    protected _onChange(change: Change): void;
    protected _onDirty(): void;
}
declare class AutoObserver extends Observer {
    readonly effect: Function;
    observed: Set<ObservedSlot>;
    constructor(effect: Function);
}

export { $$, $O, $T, Auto, AutoConfig, AutoObserver, Change, ChangeObserver, Disposable, Falsy, Observable, ObservedSlot, Observer, ObserverTarget, auto, shallowChanges };
