@katis/weave
Version:
Simple functional dependency injection
36 lines (33 loc) • 2.57 kB
text/typescript
type Providers = Record<string, Provider>;
type Resolved<D extends Providers> = {
[P in keyof D]: ProviderReturn<D[P]>;
};
type FnProvider<D, R> = (deps: D) => R;
type ProviderReturn<P extends Provider> = P extends ClassProvider<any, infer R> ? R : P extends FnProvider<any, infer R> ? R : never;
type ProviderParam<P extends Provider> = P extends ClassProvider<infer D, any> ? D : P extends FnProvider<infer D, any> ? D : never;
type ClassProvider<D, R> = HasClassProvider & {
new (deps: D): R;
};
type HasClassProvider = {
readonly isClassProvider: true;
};
type Provider<D = any, R = any> = FnProvider<D, R> | ClassProvider<D, R>;
/**
* Mixin that allows a class to be used as a Provider with `weave`,
* takes a base class parameter that the returned class will inherit from
*/
declare function Provider<B extends new (...args: any[]) => any>(Base: B): B & HasClassProvider;
/** Mixin that allows a class to be used as a Provider with `weave` */
declare function Provider(): (new () => object) & HasClassProvider;
type AllProviderDependencies<D extends Record<string, Provider>> = UnionToIntersection<{
[P in keyof D]: ProviderDependencies<D[P]>;
}[keyof D]>;
type ProviderDependencies<F> = F extends () => any ? {} : F extends new () => any ? {} : F extends (arg: infer A) => any ? A : F extends new (arg: infer A) => any ? A : never;
type UnionToIntersection<Union> = (Union extends any ? (u: Union) => void : never) extends (i: infer Intersection) => void ? Intersection : never;
declare const weave: <P_1 extends _InternalProviders & { [K in keyof UnionToIntersection<{ [P in keyof _InternalProviders]: ProviderDependencies<_InternalProviders[P]>; }[keyof _InternalProviders]>]: FullyResolvedProvider<_InternalProviders, K>; }, _InternalProviders extends Providers = P_1>(providers: P_1) => Resolved<P_1>;
type FullyResolved<D extends Providers> = {
[K in keyof AllProviderDependencies<D>]: (arg: any) => AllProviderDependencies<D>[K];
};
type FullyResolvedProvider<P extends Providers, K extends keyof AllProviderDependencies<P>> = K extends keyof P ? P[K] extends ClassProvider<any, any> ? new (...arg: ProviderParams<P, K>) => AllProviderDependencies<P>[K] : (...arg: ProviderParams<P, K>) => AllProviderDependencies<P>[K] : never;
type ProviderParams<P extends Providers, K> = K extends keyof P ? [deps: ProviderParam<P[K]>] : [deps: unknown];
export { type AllProviderDependencies, type ClassProvider, type FnProvider, type FullyResolved, Provider, type ProviderDependencies, type ProviderParams, type Providers, type Resolved, weave };