undecorated-di
Version:
Type-safe, straightforward dependency injection for TypeScript without annotations or reflect-metadata.
95 lines (79 loc) • 4.19 kB
TypeScript
type Constructor<T> = new (...args: any[]) => T;
declare class Key<T extends string = string, V = any> {
readonly name: T;
constructor(name: T);
asType(implementation: any): V;
}
type InjectableOrBindable<T = any, V extends ReadonlyArray<Key> = []> = T & {
__dependencies__: V;
};
type ParamsToKeys<P extends readonly any[]> = {
[K in keyof P]: Key<string, P[K]>;
};
type ResolvedDependencies<T extends readonly Key[]> = T extends readonly [infer First, ...infer Rest] ? First extends Key ? [
ReturnType<First["asType"]>,
...(Rest extends readonly Key[] ? ResolvedDependencies<Rest> : [])
] : never : [];
type Subset<T extends any[]> = T extends [infer First, ...infer Rest] ? [] | [First, ...Subset<Rest>] : [];
declare class BoundFunction<T extends (...args: any[]) => any, U extends readonly Key[], V extends (...args: [...ResolvedDependencies<U>, ...Parameters<T>]) => ReturnType<T>> {
readonly dependencies: U;
private key;
private bindable;
constructor(key: Key<string, T>, bindable: InjectableOrBindable<V, U>);
resolve(resolvedDependencies: ResolvedDependencies<U>): T;
}
declare class Constant<V> {
private readonly value;
constructor(value: V);
resolve(): V;
}
interface Injectable {
resolve(...args: any[]): any;
}
declare class Container<T extends Record<string, Injectable>> {
readonly injectables: T;
private resolvedInjectables;
private singletons;
private singletonPlaceholders;
constructor(injectables: T);
get<K extends keyof T & string>(key: Key<K, ReturnType<T[K]["resolve"]>>): ReturnType<T[K]["resolve"]>;
private resolveWithDependencyGraph;
private isSingleton;
private wasPreviouslyResolved;
private completesSingletonOnlyDependencyCycle;
private flagResolved;
}
declare class InjectedClass<T, U extends Constructor<T>, V extends ParamsToKeys<ConstructorParameters<U>>> {
readonly dependencies: V;
readonly isSingleton: boolean;
private injectable;
private key;
constructor(key: Key<string, T>, injectable: InjectableOrBindable<U, V>, isSingleton: boolean);
resolve(resolvedDependencies: ResolvedDependencies<V>): T;
}
declare class ContainerBuilder<T extends Record<string, Injectable>> {
readonly injectables: T;
private constructor();
static createBuilder(): ContainerBuilder<{}>;
registerClass<T extends string, S, U extends Constructor<S>, V extends ParamsToKeys<ConstructorParameters<U>>>(key: Key<T, S>, injectable: InjectableOrBindable<U, V>): ContainerBuilder<this["injectables"] & { [K in T]: InjectedClass<S, U, V>; }>;
registerSingleton<T extends string, S, U extends Constructor<S>, V extends ParamsToKeys<ConstructorParameters<U>>>(key: Key<T, S>, injectable: InjectableOrBindable<U, V>): ContainerBuilder<this["injectables"] & { [K in T]: InjectedClass<S, U, V>; }>;
registerFunction<T extends string, S extends (...args: any[]) => any, U extends readonly Key[], V extends (...args: [...ResolvedDependencies<U>, ...Parameters<S>]) => ReturnType<ReturnType<S>>>(key: Key<T, S>, bindable: InjectableOrBindable<V, U>): ContainerBuilder<this["injectables"] & { [K in T]: BoundFunction<S, U, V>; }>;
registerConstant<T extends string, V>(key: Key<T, V>, value: V): ContainerBuilder<this["injectables"] & { [K in T]: Constant<V>; }>;
build(): Container<T>;
private register;
}
type ForTypeReturnType<S extends string, T extends Record<string, Key>, U> = Keys<T & {
[K in S]: Key<S, U>;
}>;
type ForType<S extends string, T extends Record<string, Key>> = {
forType: <U>() => ForTypeReturnType<S, T, U>;
};
declare class Keys<T extends Record<string, Key>> {
readonly keys: T;
private constructor();
static createKeys(): Keys<{}>;
addKey<S extends string>(name: S): ForType<S, this["keys"]>;
}
declare function bind<T extends (...args: any[]) => any, V extends ParamsToKeys<Subset<Parameters<T>>>>(func: T, deps: V): InjectableOrBindable<T, V>;
declare function inject<T, U extends Constructor<T>, V extends ParamsToKeys<ConstructorParameters<U>>>(cls: U, dependencies: V): InjectableOrBindable<U, V>;
export { ContainerBuilder, Keys, bind, inject };