| @@ -27,12 +27,26 export interface Resolver<S extends obje | |||||
| 27 | <K extends keyof S, O extends { lazy?: false; default?: unknown }>(name: K, opts?: O): (O extends { default: infer T } ? T : never) | NonNullable<S[K]>; |
|
27 | <K extends keyof S, O extends { lazy?: false; default?: unknown }>(name: K, opts?: O): (O extends { default: infer T } ? T : never) | NonNullable<S[K]>; | |
| 28 | } |
|
28 | } | |
| 29 |
|
29 | |||
| 30 | export type DepsMap<K extends key, SK extends key> = { [k in K]: SK | Ref<SK, boolean, unknown> }; |
|
30 | export type DepsMap<S extends object> = { | |
|
|
31 | [k in key]: Refs<S> | |||
|
|
32 | }; | |||
|
|
33 | ||||
|
|
34 | export type Refs<S extends object> = { | |||
|
|
35 | [k in keyof S]: Ref<k, boolean, S[k]>; | |||
|
|
36 | }[keyof S] | keyof S; | |||
|
|
37 | ||||
|
|
38 | export type Ref<K extends key, L extends boolean, D> = { name: K, lazy?: L, default?: D | null }; | |||
| 31 |
|
39 | |||
| 32 | export type Ref<K extends key, L extends boolean, D> = { name: K, lazy?: L } | { name: K, lazy?: L, default: D }; |
|
40 | export type Lazy<T, L extends boolean> = L extends true ? () => T : T; | |
|
|
41 | ||||
|
|
42 | export type InferDefault<T> = T extends { default: infer D } ? D : never; | |||
| 33 |
|
43 | |||
| 34 |
export type Resolve |
|
44 | export type Resolve<S extends object, R> = | |
| 35 | L extends true ? () => NonNullable<S[K]> | (unknown extends D ? never : D) : NonNullable<S[K]> | (unknown extends D ? never : D); |
|
45 | R extends keyof S ? NonNullable<S[R]> : | |
|
|
46 | R extends Ref<infer K, infer L, unknown> ? | |||
|
|
47 | K extends keyof S ? Lazy<NonNullable<S[K]> | InferDefault<R>, L> : | |||
|
|
48 | never: | |||
|
|
49 | never; | |||
| 36 |
|
50 | |||
| 37 | export interface IDescriptorBuilder<S extends object, T, R extends object, O extends keyof S> { |
|
51 | export interface IDescriptorBuilder<S extends object, T, R extends object, O extends keyof S> { | |
| 38 |
|
52 | |||
| @@ -42,12 +56,9 export interface IDescriptorBuilder<S ex | |||||
| 42 | */ |
|
56 | */ | |
| 43 | factory(f: (refs: R) => T): void; |
|
57 | factory(f: (refs: R) => T): void; | |
| 44 |
|
58 | |||
| 45 |
wants<X extends DepsMap< |
|
59 | wants<X extends DepsMap<S> & Record<keyof R & keyof X, never>>(refs: X): | |
| 46 | IDescriptorBuilder<S, T, R & { |
|
60 | IDescriptorBuilder<S, T, R & { | |
| 47 | [k in keyof X]: |
|
61 | [k in keyof X]: Resolve<S, X[k]>; | |
| 48 | X[k] extends keyof S ? NonNullable<S[X[k]]> : |
|
|||
| 49 | X[k] extends Ref<infer K, infer L, infer D> ? Resolved<S, K & keyof S, L, D> : |
|
|||
| 50 | never |
|
|||
| 51 | }, O> |
|
62 | }, O> | |
| 52 |
|
63 | |||
| 53 | override<K extends O>(name: K, builder: RegistrationBuilder<S, NonNullable<S[K]>>): this; |
|
64 | override<K extends O>(name: K, builder: RegistrationBuilder<S, NonNullable<S[K]>>): this; | |
| @@ -1,7 +1,7 | |||||
| 1 | /* eslint max-classes-per-file: ["error", 20] */ |
|
1 | /* eslint max-classes-per-file: ["error", 20] */ | |
| 2 | import { describe, it } from "mocha"; |
|
2 | import { describe, it } from "mocha"; | |
| 3 | import { Container } from "../Container"; |
|
3 | import { Container } from "../Container"; | |
| 4 | import { ContainerServices } from "../interfaces"; |
|
4 | import { ContainerServices, DepsMap, Refs, Resolver } from "../interfaces"; | |
| 5 | import { fluent } from "../traits"; |
|
5 | import { fluent } from "../traits"; | |
| 6 |
|
6 | |||
| 7 | class Foo { |
|
7 | class Foo { | |
| @@ -31,6 +31,19 interface ServicesB { | |||||
| 31 | zoo?: Foo; |
|
31 | zoo?: Foo; | |
| 32 | } |
|
32 | } | |
| 33 |
|
33 | |||
|
|
34 | declare const resolver: Resolver<Services>; | |||
|
|
35 | ||||
|
|
36 | const foo = resolver("foo", {lazy: true}); | |||
|
|
37 | ||||
|
|
38 | const mmap = <X extends DepsMap<Services, string>>(m: X) => {}; | |||
|
|
39 | ||||
|
|
40 | const refs: Refs<Services> = {name: "bar", default: undefined}; | |||
|
|
41 | ||||
|
|
42 | mmap({ | |||
|
|
43 | fooz: {name: "foo", lazy: false, default: undefined }, | |||
|
|
44 | ooz: "bar" | |||
|
|
45 | }); | |||
|
|
46 | ||||
| 34 | interface SharedServices { |
|
47 | interface SharedServices { | |
| 35 | foo: Foo; |
|
48 | foo: Foo; | |
| 36 |
|
49 | |||
| @@ -47,13 +60,17 const config = fluent() | |||||
| 47 | .lifetime("context") // тип активации, время жизни |
|
60 | .lifetime("context") // тип активации, время жизни | |
| 48 | .wants({ |
|
61 | .wants({ | |
| 49 | zoo: "zoo", // зависимость |
|
62 | zoo: "zoo", // зависимость | |
|
|
63 | bar: "bar", | |||
| 50 |
|
|
64 | ||
| 51 |
zoo |
|
65 | $zoo: { name: "foo", lazy: true, } // отложенная активация, | |
| 52 | //фабричный метод |
|
66 | //фабричный метод | |
| 53 | }) |
|
67 | }) | |
| 54 | .factory(({ zoo$ }) => // фабрика получает объект с именованными зависимостями |
|
68 | .wants({ | |
|
|
69 | zoom: "bar" | |||
|
|
70 | }) | |||
|
|
71 | .factory(({ $zoo, zoo }) => // фабрика получает объект с именованными зависимостями | |||
| 55 | // удобно для деструктурирования |
|
72 | // удобно для деструктурирования | |
| 56 |
new Bar(zoo |
|
73 | new Bar($zoo) // создается экземпляр сервиса | |
| 57 | ), |
|
74 | ), | |
| 58 | foo: it => it.factory(() => new Foo()), |
|
75 | foo: it => it.factory(() => new Foo()), | |
| 59 | baz: it => it.value(new Foo()) |
|
76 | baz: it => it.value(new Foo()) | |
General Comments 0
You need to be logged in to leave comments.
Login now
