declare const brand: unique symbol;
interface Brand<B extends object> {
    readonly [brand]: B;
}
/**
 * Branded object type
 */
export declare type Branded<T, B extends object> = [T & Brand<B>][0];
declare type BrandedObject<B extends object, X extends object> = (object extends X ? [Brand<B>][0] : Branded<X, B>);
/**
 * Branding function definition
 */
export interface Branding<B extends object, X extends object = object> extends Brand<B> {
    /**
     * Brands an object
     * @param obj the object to brand
     * @throws Error if the object is already branded
     */
    <T extends X>(obj: T): Branded<T, B>;
    /**
     * Asserts this brand for the given object.
     * @param obj the object to assert brand on
     * @throws Error when object is not branded.
     */
    assert(obj: object): asserts obj is BrandedObject<B, X>;
    /**
     * Checks if the given object has this brand.
     * @param obj the object to check
     */
    has(obj: object): obj is BrandedObject<B, X>;
    /**
     * Refines this branding with a new outer brand. The resulting branding will
     * be a composition (merge) between the inner and outer brand.
     * This method is actually a shortcut for createBranding and subsequent merge.
     *
     * @param newBrand the new brand that refines the current one
     * @param callback a callback invoked when object are branded with the refined branding
     */
    refine<N extends object, Y extends X = X>(newBrand: N, callback?: BrandingCallback<N, Y>): Branding<N & B, Y>;
    /**
     * Merges the given branding with the current one.
     *
     * @param branding the other brand to merge with
     */
    merge<C extends object, Y extends X = X>(branding: Branding<C, Y>): Branding<B & C, Y>;
    /**
     * Returns this Branding with a different generic bound for target objects.
     */
    generic<T extends object>(): Branding<B, T>;
}
/**
 * A branding callback invoked during object branding
 */
export declare type BrandingCallback<B extends object, T extends object = object> = (obj: T, brand: B) => void;
/**
 * Creates a new brand, identified by the provided branding object.
 *
 * @param brandObject An object that represents the brand. The shape of this object should be unique, and symbols may be used as unique keys.
 * @param callback An optional callback with variable arguments which is invoked during object branding
 */
export declare function createBranding<B extends object, X extends object = object>(brandObject: B, callback?: BrandingCallback<B, X>): Branding<B, X>;
export {};
