/// <reference types="@rbxts/types" />
/// <reference types="@rbxts/types" />
/// <reference types="@rbxts/compiler-types" />
declare type AttributeRecord<K extends string, T extends AttributeValue> = {
    [P in K]: T;
};
/**
 * Attributes wrapper class. Enforces default attribute values
 * and attribute typings.
 *
 * ```ts
 * const attrs = new Attributes(myInstance, {
 * 	name: "default_name",
 * 	points: 0,
 * 	xp: 0,
 * 	cool: false,
 * });
 *
 * print(attrs.attributes.points);
 * attrs.set("points", 10);
 * attrs.destroy();
 * ```
 */
export declare class Attributes<T extends AttributeRecord<string, AttributeValue>, I extends Instance = Instance> {
    private readonly instance;
    /**
     * Attributes bound to the instance. This is a readonly
     * dictionary. To set the value of an attribute, use
     * the `set()` method.
     */
    readonly attributes: Readonly<T>;
    private readonly attr;
    private readonly connections;
    private readonly onChangedCallbacks;
    constructor(instance: I, defaultAttributes: T);
    private handleOnChange;
    /**
     * Set the value of an attribute.
     *
     * ```ts
     * attrs.set("points", 10);
     * ```
     *
     * @param key Attribute name
     * @param value Attribute value
     */
    set<K extends keyof T>(key: K, value: T[K]): void;
    /**
     * Listen for changes of a given attribute.
     *
     * ```ts
     * attrs.onChanged("points", (newPoints, oldPoints) => {
     * 	print(`Points changed from ${oldPoints} to ${newPoints}`);
     * });
     * ```
     *
     * @param key Attribute name
     * @param handler Callback
     * @returns Cleanup function
     */
    onChanged<K extends keyof T>(key: K, handler: (newValue: T[K] | undefined, oldValue: T[K] | undefined) => void): () => void;
    /**
     * Observe the value of a given attribute. Similar to `onChange()`,
     * except it also fires immediately with the given attribute value.
     *
     * ```ts
     * attrs.observe("points", (points) => print(`Points: ${points}`));
     * ```
     *
     * @param key Attribute name
     * @param observer Observer function
     * @returns Cleanup function
     */
    observe<K extends keyof T>(key: K, observer: (value: T[K] | undefined) => void): () => void;
    /**
     * Clean up this Attributes instance. This disconnects all
     * of the connections that listen for changed attributes.
     *
     * If the attached instance of this Attributes object was
     * destroyed, then this method does not need to be called.
     *
     * This does _not_ clear the attributes on the given instance.
     */
    destroy(): void;
}
export {};
