import { EventEmitter } from './event-emitter';
import { Injection } from './injection';
import { Lifetime } from './lifetime';
import { Constructor, ContainerEventMap, Resolvable, TypeInfo } from './types';
export interface ResolveHistoryItem {
    name: string;
    type: 'MethodInjection' | 'PropertyInjection' | null;
}
export interface ResolveContext {
    history: ResolveHistoryItem[];
}
type RegistrationArgs = PartialOrNull<RegistrationOptions> | RegistrationOptions['key'];
export interface RegistrationOptions {
    key: string;
    lifetime: Lifetime;
    injections: Injection[];
    argAlias: string;
}
type Optional<T> = T | undefined | null;
type PartialOrNull<T> = {
    [P in keyof T]?: T[P] | null;
};
export declare class Registration {
    readonly name: string;
    readonly lifetime: Lifetime;
    readonly injections: Injection[];
    constructor(name: string, lifetime: Optional<Lifetime>, injections: Optional<Injection[]>);
}
export declare class TypeRegistration extends Registration {
    readonly typeInfo: TypeInfo;
    constructor(name: string, lifetime: Optional<Lifetime>, injections: Optional<Injection[]>, typeInfo: TypeInfo);
}
export declare class InstanceRegistration<T = unknown> extends Registration {
    readonly instance: T;
    constructor(name: string, lifetime: Optional<Lifetime>, injections: Optional<Injection[]>, instance: T);
}
export declare class FactoryRegistration<T = unknown> extends Registration {
    readonly factory: (container: Container) => T;
    constructor(name: string, lifetime: Optional<Lifetime>, injections: Optional<Injection[]>, factory: (container: Container) => T);
}
export declare class DelegateRegistration extends Registration {
    readonly delegateKey: string;
    constructor(alias: string, delegateKey: string);
}
export declare class Container<TResolveMap extends Record<string, any> = Record<string, unknown>> extends EventEmitter<ContainerEventMap> implements Resolvable<TResolveMap> {
    readonly parent: Container | null;
    private readonly registrations;
    private graph;
    private readonly builder;
    constructor(parent?: Container);
    private addDependencyToGraph;
    registerType<T>(ctor: Constructor<T>, options?: RegistrationArgs): this;
    registerTypeAndArgAlias<T>(ctor: Constructor<T>, key?: string | null, alias?: string | null): this;
    registerAlias(key: string, alias: string): this;
    registerArgAlias(key: string, alias: string): this;
    /**
     * Registers a specific object instance
     */
    registerInstance<T = unknown>(instance: T, options?: RegistrationArgs): this;
    registerInstanceAndArgAlias<T = unknown>(instance: T, key?: string | null, alias?: string | null): this;
    /**
     * Registers a factory function for a type that will create
     * the object
     */
    registerFactory<T = unknown>(factory: (container: Container) => T, options?: RegistrationArgs): this;
    registerFactoryAndArgAlias<T = unknown>(factory: (container: Container) => T, key: string, alias: string): this;
    /**
     * Determines if something is registered with the given key
     */
    isRegistered(key: Constructor | string): boolean;
    private resolveExisting;
    /**
     * Resolve a type to an instance synchronously
     */
    resolveSync<T = never, K extends keyof TResolveMap = never>(key: [T] extends [never] ? K : Constructor<T> | string, context?: ResolveContext): [T] extends [never] ? TResolveMap[K] : T;
    /**
     * Resolve a type to an instance asynchronously
     */
    resolve<T = never, K extends keyof TResolveMap = never>(key: [T] extends [never] ? K : Constructor<T> | string, context?: ResolveContext): Promise<[T] extends [never] ? TResolveMap[K] : T>;
    /**
     * Same as resolve(), but won't ever reject
     */
    tryResolve<T = never, K extends keyof TResolveMap = never>(key: [T] extends [never] ? K : Constructor<T> | string): Promise<([T] extends [never] ? TResolveMap[K] : T) | undefined>;
    /**
     * Same as resolveSync(), but won't ever throw
     */
    tryResolveSync<T = never, K extends keyof TResolveMap = never>(key: [T] extends [never] ? K : Constructor<T> | string): ([T] extends [never] ? TResolveMap[K] : T) | undefined;
    /**
     * Performs injection on an object asynchronously
     */
    inject<T = unknown>(instance: T, key?: string): Promise<void>;
    /**
     * Performs injection on an object synchronously
     */
    injectSync<T = unknown>(instance: T, key?: string): void;
    /**
     * Creates a clone of the container in its current state
     */
    createChildContainer(withEvents?: boolean): Container<TResolveMap>;
}
export {};
