| 1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 |
| @@ -49,6 +49,8 typescript { | |||||
| 49 | compilerOptions { |
|
49 | compilerOptions { | |
| 50 | types = [] |
|
50 | types = [] | |
| 51 | declaration = true |
|
51 | declaration = true | |
|
|
52 | experimentalDecorators = true | |||
|
|
53 | //strict = true | |||
| 52 |
|
54 | |||
| 53 | if(symbols != 'none') { |
|
55 | if(symbols != 'none') { | |
| 54 | sourceMap = true |
|
56 | sourceMap = true | |
| @@ -10,28 +10,41 type Injector<T> = { | |||||
| 10 | [k in keyof T]: Setter; |
|
10 | [k in keyof T]: Setter; | |
| 11 | }; |
|
11 | }; | |
| 12 |
|
12 | |||
|
|
13 | type Compatible<T1, T2> = T1 extends T2 ? any : never; | |||
|
|
14 | ||||
|
|
15 | type SetterType<T> = T extends (v: infer V) => void ? V : never; | |||
|
|
16 | ||||
|
|
17 | type Tuple<T = any> = Parameters<(...args: T[]) => void>; | |||
|
|
18 | ||||
|
|
19 | interface Newable<A extends Tuple, T> { | |||
|
|
20 | new (...params: A): T; | |||
|
|
21 | prototype: T; | |||
|
|
22 | } | |||
|
|
23 | ||||
|
|
24 | type MapTuple<T, A extends (keyof T)[]> = { [K in keyof A] : K extends number ? T[ A[K] ] : A[K] }; | |||
|
|
25 | ||||
| 13 | export class Builder<T, S> { |
|
26 | export class Builder<T, S> { | |
| 14 |
provides( |
|
27 | provides() { | |
| 15 | return <C extends Constructor<T>>(constructor: C) => { |
|
28 | return <C extends Constructor<T>>(constructor: C) => { | |
| 16 | return constructor; |
|
29 | return constructor; | |
| 17 | }; |
|
30 | }; | |
| 18 | } |
|
31 | } | |
| 19 |
|
32 | |||
| 20 | inject<K extends keyof S>(dependency: K) { |
|
33 | inject<K extends keyof S>(dependency: K) { | |
| 21 | return <M extends keyof T>(target: any, memberName: M, descriptor: TypedPropertyDescriptor<Setter<S[K]>> ) => { |
|
34 | // K = "bar" | |
|
|
35 | // M = "setValue" | |||
|
|
36 | // S[K] = Bar | |||
|
|
37 | // T[M] = (value: string) => void | |||
|
|
38 | // P[m] = (value: V) => void | |||
|
|
39 | return <P, M extends keyof (T | P)>(target: P, memberName: M, descriptor: TypedPropertyDescriptor<Compatible<T[M], Setter<S[K]>>>) => { | |||
| 22 |
|
40 | |||
| 23 | }; |
|
41 | }; | |
| 24 | } |
|
42 | } | |
| 25 |
|
43 | |||
| 26 |
|
|
44 | dependencies<D extends (keyof S)[]>(...deps: D) { | |
| 27 | return <M extends keyof T>(target: any, memberName: M, descriptor: TypedPropertyDescriptor<S[K]> ) => { |
|
45 | return <C extends Constructor<T>>(constructor: MapTuple<S, D> extends ConstructorParameters<C> ? C : never) => { | |
| 28 |
|
46 | return constructor; | ||
| 29 | }; |
|
47 | } ; | |
| 30 | } |
|
48 | } | |
|
|
49 | ||||
| 31 | } |
|
50 | } | |
| 32 |
|
||||
| 33 | export function inject<I extends Injector<I> >(dependency: string) { |
|
|||
| 34 | return <M extends keyof I>(target: any, memberName: M, descriptor: TypedPropertyDescriptor<I[M]> ) => { |
|
|||
| 35 |
|
||||
| 36 | }; |
|
|||
| 37 | } |
|
|||
| @@ -3,10 +3,16 import { Foo } from "./Foo"; | |||||
| 3 | export class Bar { |
|
3 | export class Bar { | |
| 4 | name = "bar"; |
|
4 | name = "bar"; | |
| 5 |
|
5 | |||
| 6 | foo: Foo; |
|
6 | foo: Foo | undefined; | |
| 7 |
|
7 | |||
| 8 | constructor(_opts) { |
|
8 | constructor(_opts?: { foo?: Foo; }) { | |
| 9 | if (_opts && _opts.foo) |
|
9 | if (_opts && _opts.foo) | |
| 10 | this.foo = _opts.foo; |
|
10 | this.foo = _opts.foo; | |
| 11 | } |
|
11 | } | |
|
|
12 | ||||
|
|
13 | getFoo() { | |||
|
|
14 | if (this.foo === undefined) | |||
|
|
15 | throw new Error("The foo isn't set"); | |||
|
|
16 | return this.foo; | |||
| 12 | } |
|
17 | } | |
|
|
18 | } | |||
| @@ -2,22 +2,32 import { Builder } from "../di/Annotatio | |||||
| 2 | import { Bar } from "./Bar"; |
|
2 | import { Bar } from "./Bar"; | |
| 3 | import { Foo } from "./Foo"; |
|
3 | import { Foo } from "./Foo"; | |
| 4 |
|
4 | |||
| 5 | export interface Injector<T> { |
|
5 | const builder = new Builder<Box<Bar>, { bar: Bar; foo: Foo; obj: object }>(); | |
| 6 | setValue(value: T); |
|
|||
| 7 | } |
|
|||
| 8 |
|
6 | |||
| 9 | const builder = new Builder<Box<any>, { bar: Bar; foo: Foo}>(); |
|
7 | @builder.provides() | |
|
|
8 | @builder.dependencies("bar") | |||
|
|
9 | export class Box<T> { | |||
|
|
10 | private _value: T | undefined; | |||
| 10 |
|
11 | |||
| 11 | @builder.provides("barBox") |
|
12 | constructor(value: T) { | |
| 12 | export class Box<T> implements Injector<T> { |
|
13 | this._value = value; | |
| 13 | private _value: T; |
|
14 | } | |
| 14 |
|
15 | |||
| 15 | @builder.inject("bar") |
|
16 | @builder.inject("bar") | |
| 16 | setValue(value: T) { |
|
17 | setValue(value: T) { | |
| 17 | this._value = value; |
|
18 | this._value = value; | |
| 18 | } |
|
19 | } | |
| 19 |
|
20 | |||
|
|
21 | ||||
|
|
22 | @builder.inject("foo") | |||
|
|
23 | setObj(value: object) { | |||
|
|
24 | ||||
|
|
25 | } | |||
|
|
26 | ||||
| 20 | getValue() { |
|
27 | getValue() { | |
|
|
28 | if (this._value === undefined) | |||
|
|
29 | throw new Error("Trying to get a value from the empty box"); | |||
|
|
30 | ||||
| 21 | return this._value; |
|
31 | return this._value; | |
| 22 | } |
|
32 | } | |
| 23 |
} |
|
33 | } No newline at end of file | |
| @@ -1,7 +1,7 | |||||
| 1 | { |
|
1 | { | |
| 2 | "extends": "../tsconfig", |
|
2 | "extends": "../tsconfig", | |
| 3 | "compilerOptions": { |
|
3 | "compilerOptions": { | |
| 4 | "rootDir": "ts", |
|
4 | //"rootDir": "ts", | |
| 5 | "baseUrl": ".", |
|
5 | "baseUrl": ".", | |
| 6 | "rootDirs": [ |
|
6 | "rootDirs": [ | |
| 7 | "ts", |
|
7 | "ts", | |
| @@ -4,6 +4,7 | |||||
| 4 | "experimentalDecorators": true, |
|
4 | "experimentalDecorators": true, | |
| 5 | "noEmitOnError": true, |
|
5 | "noEmitOnError": true, | |
| 6 | "listFiles": true, |
|
6 | "listFiles": true, | |
|
|
7 | "strict": true, | |||
| 7 | "types": [], |
|
8 | "types": [], | |
| 8 | "target": "ES5", |
|
9 | "target": "ES5", | |
| 9 | "lib": ["es5", "es2015.promise", "es2015.symbol", "es2015.iterable", "dom", "scripthost"] |
|
10 | "lib": ["es5", "es2015.promise", "es2015.symbol", "es2015.iterable", "dom", "scripthost"] | |
General Comments 0
You need to be logged in to leave comments.
Login now
