export declare namespace Observer {
    interface IObserver {
        /** Returns @true if object is observed (converted via observer.make()) */
        isObserved(obj: any): boolean;
        /** Make observable object to detect changes;
         * @see {@link Proxy} */
        make<T extends object>(obj: T, opts?: Options<T>): Observer.Observed<T>;
        /** Listen for any props changing on the observed; callback is called per each prop-changing
         * @returns callback to removeListener */
        onPropChanged<T extends Observer.Observed<object>>(target: T, callback: Observer.PropCallback<T>): () => void;
        /** Listen for any changing on the observed; callback is called single time per bunch of props-changing
         * @returns callback to removeListener */
        onChanged<T extends Observer.Observed<object>>(target: T, callback: Observer.Callback<T>): () => void;
    }
    interface Options<T> {
        /** Point array of nested prop-names to exclude from observer or true to exclude every nested property of object
         * @tutorial Troubleshooting
         * * point ['items'] to exclude any nested props of property with name `items` from obsserved of obj.items
         * * obj.nested.items - will be also fit the rule
         * * point `true` to exclude all nested */
        excludeNested?: Array<keyof T> | boolean;
    }
    type Observed<T extends object = object> = {
        [K in keyof T]: T[K] extends Record<string, unknown> ? Observed<T[K]> : T[K];
    };
    type BasicPropEvent<T, K extends keyof T> = {
        /** Previous value */
        prev: T[K] extends Func ? ReturnType<T[K]> : T[K] | undefined;
        /** Current/next value */
        next: T[K] extends Func ? ReturnType<T[K]> : T[K] | undefined;
        /** Prop that is changed; For arrays it can be `length`, for Set,MapSet - `size` */
        prop: K;
        /** Object to that prop related */
        target: T;
    };
    type DateEvent<T extends Date> = BasicPropEvent<T, "valueOf">;
    type MapSetEvent<T extends Set<any> | Map<any, any>> = BasicPropEvent<T, "size">;
    type PropEvent<T, K extends keyof T> = T extends Date ? DateEvent<T> : T extends Set<any> | Map<any, any> ? MapSetEvent<T> : BasicPropEvent<T, K>;
    type PropCallback<T> = <K extends keyof T>(event: PropEvent<T, K>) => void;
    type ObjectEvent<T> = {
        props: T extends Date ? Array<"valueOf"> : T extends Set<any> | Map<any, any> ? Array<"size"> : Array<keyof T>;
        target: T;
    };
    type Callback<T> = (event: ObjectEvent<T>) => void;
}
/** Helper to detect object changes;
 * @example
 * const raw = { date: new Date(), period: 3, nestedObj: { val: 1} };
 * const obj = observer.make(raw);
 * const removeListener = observer.onPropChanged(obj, (e) => console.warn(e));
 * const removeListener2 = observer.onChanged(obj, (e) => console.warn(e));
 * obj.period = 5; // events are fired after 1ms
 * removeListener();
 * removeListener2(); */
declare const observer: Observer.IObserver;
export default observer;
