UNPKG

undecorated-di

Version:

Type-safe, straightforward dependency injection for TypeScript without annotations or reflect-metadata.

95 lines (79 loc) 4.19 kB
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 };