import { IDependencies, IInjections, Injected } from './AbstractResolvable';
import { AbstractClass, AbstractFn, Injectable } from './utils';
export declare type ResolveForFunction = <I extends IInjections = {}>(classImpl: AbstractClass | AbstractFn, injections?: I, instance?: object, args?: unknown[]) => IDependencies<I>;
export declare type ResolveRequirementsFunction = <R extends any[] = any[], C extends object = object>(requirements: R, classImpl: C) => C;
declare const overrideSymbol: unique symbol;
/**
 * Interface that forces users to make type safe overrides
 * @description override result
 * @template T type of dependency that have to be overwritten
 */
export interface IOverrideResult<T extends Injectable = Injectable> {
    [overrideSymbol]: [T, Injected<T>];
}
/**
 * Function that meant to be used as only way for specifying overrides
 * @description creates a `[key, value]` pair describing override
 * @template T type of dependency key that has to be overwritten
 * @param key actual key that has to be overwritten
 * @param value value that will be passed as dependency for this `key`
 * @returns object with symbol property which point to `[key, value]` pair
 */
export declare function override<T extends Injectable = Injectable>(key: T, value: Injected<T>): IOverrideResult<T>;
/**
 * Class that is responsible for resolving dependencies and requirements
 * @description contains all resolved dependencies, resolvable class implementations
 * and methods that used by `Resolvable` factories in order to create properly resolved
 * classes with dependencies
 * > **NOTE:** it also meant to be extended in order to provide first-class support
 * for some particular frameworks e.g. `react`
 */
export declare class Resolver {
    /**
     * WeakMap where `key` points to resolved and initialized `dependency`
     * @description map of all resolved dependencies
     */
    protected injectionRoot: WeakMap<Injectable, unknown>;
    /**
     * WeakMap where `key` is resolvable class and `value` is object with resolved `dependencies`
     * @description resolved dependencies for resolvable class implementations
     */
    protected implementations: WeakMap<AbstractClass | AbstractFn, unknown>;
    /**
     * Creates an instance of resolver.
     * @param [overrides]
     */
    constructor(overrides?: IOverrideResult[]);
    /**
     * Entry point for resolving requirements for particular resolvable class
     * @description resolves `requirements` for `classImpl` and applies them to `ApplicationRoot`
     * > **NOTE:** default implementation does nothing, since only Resolver for specific framework
     * knows how to apply requirements to particular environment
     * @template R type of `requirements` tuple
     * @template C type of `classImpl` constructor
     * @param requirements tuple of specific requirements that should be met by hosting application
     * @param classImpl particular resolvable class implementation
     * @returns `classImpl` or something with exactly same interface
     */
    resolveRequirements<R extends any[], C extends object>(requirements: R, classImpl: C): C;
    /**
     * Entry point for resolving dependencies of particular instance
     * @description resolves `injections` for `instance` of `classImpl` resolvable class
     * @template I type of `injections` dictionary
     * @param classImpl class constructor that was used for creating this instance
     * @param [injections] dictionary of dependencies that should be resolved and initialized
     * @param [instance] particular class instance
     * @param [args] arguments that were passed to constructor function for creating `instance`
     * @returns dictionary of resolved and initialized dependencies
     */
    resolveFor<I extends IInjections = {}>(classImpl: AbstractClass | AbstractFn, injections?: I, instance?: object, args?: unknown[]): IDependencies<I>;
    /**
     * This method is used internally to properly initialize dependency
     * @description initializes injectable `obj`
     * > **NOTE:** this function is pure, but it's possible that ancestors may need
     * another solution for initializing instances, because of framework
     * requirements, conventions and best practices
     * @param obj dependency that has to be initialized
     * @returns initialized dependency
     */
    protected initialize<T extends Injectable = Injectable>(obj: T): any;
    /**
     * This method is used to inject resolved `dependency` for `injectionKey`
     * @description Injects resolver
     * @template T type of `injectionKey` that maps to type of `dependency` value
     * @param injectionKey actual key of `dependency`
     * @returns resolved `dependency` instance
     */
    protected inject<T extends Injectable = Injectable>(injectionKey: T): Injected<T>;
    /**
     * This method works with result of `override` helper function
     * @description Sets override for particular `injectionKey`
     * @template T type of `injectionKey` that maps to type of `dependency` value
     * @param overridePair actual `[key, value]` pair retrieved from override helper
     */
    protected setOverride<T extends Injectable = Injectable>(overridePair: IOverrideResult<T>): void;
}
export {};
//# sourceMappingURL=Resolver.d.ts.map