/**
 * @template T
 */
declare class ContainerKey<T> {
    #private;
    /**
     *
     * @param {string} description
     */
    constructor(description: string);
    get description(): string;
    get type(): T;
}

declare enum Scopes {
    /**
     * Creates a single instance on the application.
     */
    SINGLETON = 0,
    /**
     * Creates a single instance per container context.
     */
    CONTEXT = 1,
    /**
     * Creates a new instance on every injection.
     */
    INSTANCE = 2,
    /**
     * Creates a single instance on the container.
     */
    CONTAINER = 3
}

/**
 * @template {object} T
 * @typedef {new (...args: any[]) => T} ClassConstructor
 */
type ClassConstructor<T> = (new (...args: any[]) => T) | (new () => T);
/**
 * @template {object} T
 * @typedef {(container: Container) => T} Factory
 */
type Factory<T> = (container: Container) => T;
/**
 * @template {object} T
 * @typedef {() => ClassConstructor<T> | ContainerKey<T>} KeyProvider
 */
type KeyProvider<T> = () => ClassConstructor<T> | ContainerKey<T>;

declare class Container {
    #private;
    constructor(parent?: Container);
    /**
     *
     * @template T
     * @param {ContainerKey<T>} key
     * @param {Factory<T>} factory
     * @param {Scopes} [scope=Scopes.SINGLETON]
     */
    register<T>(key: ContainerKey<T>, factory: Factory<T>, scope?: Scopes): void;
    /**
     *
     * @template T
     * @param {ClassConstructor<T>} key
     * @param {Factory<T>} [factory]
     * @param {Scopes} [scope=Scopes.SINGLETON]
     */
    register<T>(key: ClassConstructor<T>, factory?: Factory<T>, scope?: Scopes): void;
    /**
     *
     * @template {any} T
     * @param {ClassConstructor<T> | ContainerKey<T>} key
     * @returns {T} The value stored on the `key`
     */
    get<T>(key: ClassConstructor<T> | ContainerKey<T>): T;
    /**
     *
     * @template {any} T
     * @param {KeyProvider.<T>} key
     * @returns {T}
     */
    lazy<T>(key: KeyProvider<T>): T;
    /**
     * Runs a function within a context and returns its return value.
     * The store is not accessible outside of the callback function or
     * the asynchronous operations created within the callback.
     *
     * @param callback
     * @returns
     */
    context<T>(callback: () => T | Promise<T>): T | Promise<T>;
}

export { Container, ContainerKey, Scopes };
