/** A generic constructor */ type Constructor = abstract new (...args: any) => T; /** The _type_ for a binding, either a `Constructor` or a `string`. */ type Binding = Constructor | string; /** The _type_ of a binding in the context of an `Injector`. */ type InjectorBinding> = Components | (keyof Provisions & string) | PromisedBinding; /** A tuple of `InjectorBinding`s (what's needed by `$inject`). */ type InjectTuple> = readonly [InjectorBinding, ...(InjectorBinding)[]]; /** * Check that an `Injector`'s static `$inject` member matches the `Injector`'s * own components and provisions */ type CheckInject> = Inject extends readonly [] ? readonly [] : Inject extends readonly [infer I1] ? I1 extends PromisedBinding ? I2 extends keyof Provisions ? readonly [PromisedBinding] : I2 extends Extract ? readonly [PromisedBinding] : readonly [PromisedBinding] : I1 extends keyof Provisions ? readonly [I1] : I1 extends Extract ? readonly [I1] : readonly [never] : Inject extends readonly [infer I1, ...infer I2] ? readonly [ ...CheckInject<[I1], Components, Provisions>, ...CheckInject ] : readonly [Components | keyof Provisions, ...(Components | keyof Provisions)[]]; /** * Map the contents of the static `$inject` member to their types, resolving * named provisions. */ type MapInject> = Inject extends readonly [] ? readonly [] : Inject extends readonly [infer I1] ? I1 extends PromisedBinding ? I2 extends keyof Provisions ? readonly [Promise] : I2 extends Constructor ? readonly [Promise>] : readonly [never] : I1 extends keyof Provisions ? readonly [Provisions[I1]] : I1 extends Constructor ? readonly [InstanceType] : readonly [never] : Inject extends readonly [infer I1, ...infer I2] ? readonly [ ...MapInject<[I1], Provisions>, ...MapInject ] : readonly [never]; /** * Check that an `Injectable` is valid for a given `Injector`. */ type CheckInjectable, // the `Injectable` to check Components extends Constructor, // the `Injector`'s components Provisions extends Record> = I extends { $inject: infer Inject; } ? { $inject: CheckInject; new (...args: MapInject): any; } : I extends new () => any ? I : { $inject: InjectTuple; }; /** * Return the unrolled type of a `Promise` */ type UnrollPromise = T extends Promise ? UnrollPromise : T; /** * Override the type for an `Injector`'s existing provision, or add a new one */ type ExtendProvisions, // the `Injector`'s provisions P extends string, // the new (string) key of the provision T> = { [key in P | keyof Provisions]: key extends P ? UnrollPromise : Provisions[key]; }; /** A constant symbol identifying a _promised binding_. */ declare const promisedBinding: unique symbol; /** Declare a _binding_ to be _promised_ (inject its `Promise`). */ export declare function promise(binding: B): PromisedBinding; export interface PromisedBinding { [promisedBinding]: B; } /** An `Injectable` defines a constructor for an injectable class */ export interface Injectable, T = any> { prototype: T; new (...args: any): T; $inject?: InjectTuple; } /** * The `Injections` interface abstracts the idea of getting bound and * provisioned instances from an `Injector`, injecting new `Injectable` * instances, and creating sub-`Injector`s. */ export interface Injections = {}> { /** Get a _bound_ instance from an `Injector`. */ get(component: C): Promise>; /** Get a _provisioned_ instance from an `Injector`. */ get

(provision: P): Promise; /** * Create a new instance of the specified `Injectable`, providing it with all * necessary injections. * * @param injectable The constructor of the instance to create. */ inject>(injectable: I & CheckInjectable): Promise>; /** Create a sub-`Injector` child of the current one. */ injector(): Injector; } /** A `Factory` is a _function_ creating instances of a given type. */ export type Factory = Record, T = any> = (injections: Injections) => T | Promise; /** * The `Injector` class acts as a registry of components and provisions, * creating instances and injecting dependencies. */ export declare class Injector = {}> implements Injections { #private; /** Bind an `Injectable` to this `Injector`. */ bind>(injectable: I & CheckInjectable): Injector; /** Bind an `Injectable` to a `Constructor` in this `Injector`. */ bind>>(component: C, injectable: I & CheckInjectable): Injector; /** Bind an `Injectable` to a name in this `Injector`. */ bind

>(provision: P, injectable: I & CheckInjectable): Injector>>; /** Use a `Factory` to create instances bound to the given `Constructor`. */ create(component: C, factory: Factory>): Injector; /** Use a `Factory` to create instances bound to the given name. */ create

>(provision: P, factory: F): Injector>>; /** Provision an environment variable. */ env(variable: E, defaultValue?: string): Injector>; /** Use the given instance binding it to to the given `Constructor`. */ use(component: C, instance: InstanceType | PromiseLike>): Injector; /** Use the given instance binding it to to the given name. */ use

(provision: P, instance: T | PromiseLike): Injector>; /** Get a _bound_ instance from an `Injector` */ get(component: C): Promise>; /** Get a _provisioned_ instance from an `Injector` */ get

(provision: P): Promise; /** * Create a new instance of the specified `Injectable`, providing all * necessary injections. * * @param injectable The constructor of the instance to create. */ inject>(injectable: I & CheckInjectable): Promise>; /** * Simple utility method to invoke the factory with the correct `Injections` * and return its result. * * This can be used to alleviate issues when top-level await is not available. */ make>(factory: F): ReturnType; /** Create a sub-`Injector` child of this one. */ injector(): Injector; } export {};