@@ -24,42 +24,71 @@ export type Tail<T> = T extends Array<any>
24
24
API Types
25
25
*/
26
26
27
- type ContextReference < TState > = {
27
+ type ContextReference < TState , TContexts extends Contexts > = {
28
28
state : TState
29
29
setState : React . Dispatch < React . SetStateAction < TState > >
30
+ stores : InferStores < TContexts >
30
31
}
31
32
32
- type Action < TState , TArgs extends never [ ] = never [ ] , TReturn = any > =
33
- ( contextReference : ContextReference < TState > , ...args : TArgs ) => TReturn
33
+ type Action < TState , TContexts extends Contexts , TArgs extends never [ ] = never [ ] , TReturn = any > =
34
+ ( contextReference : ContextReference < TState , TContexts > , ...args : TArgs ) => TReturn
34
35
35
- type Actions < TState > = { [ key : string ] : Action < TState > }
36
+ type Actions < TState , TContexts extends Contexts > = { [ key : string ] : Action < TState , TContexts > }
36
37
37
- type MappedActions < TState , TActions extends Actions < TState > > = {
38
+ type MappedActions < TState , TContexts extends Contexts , TActions extends Actions < TState , TContexts > > = {
38
39
[ P in keyof TActions ] : ( ...args : DropFirst < Params < TActions [ P ] > > ) => RetType < TActions [ P ] >
39
40
}
40
41
41
- type Store < TState , TActions extends Actions < TState > > =
42
- TActions extends undefined ? TState : TState & MappedActions < TState , TActions >
42
+ type Store < TState , TContexts extends Contexts , TActions extends Actions < TState , TContexts > > =
43
+ TActions extends undefined ? TState : TState & MappedActions < TState , TContexts , TActions >
43
44
45
+ type Context < T = any > = React . Context < T >
46
+ type Contexts = { [ key : string ] : Context }
47
+
48
+ export type Params1 < T extends ( ...args : never [ ] ) => unknown > = T extends ( ...args : infer P ) => any ? P : never ;
49
+
50
+ type InferStore < TContext extends React . Context < any > > =
51
+ TContext extends React . Context < infer TStore > ? TStore : never
52
+
53
+ type InferStores < TContexts extends Contexts > = {
54
+ [ P in keyof TContexts ] : InferStore < TContexts [ P ] >
55
+ }
44
56
/*
45
57
Logic
46
58
*/
47
59
48
- export default function createStoreContext < TState , TActions extends Actions < TState > = { } > (
49
- initialState : TState ,
50
- actions ?: TActions
51
- ) : [ React . Context < Store < TState , TActions > > , React . FC ] {
52
- const store = { ...initialState , ...mapActionsToDefault ( initialState , actions ) } as Store < TState , TActions >
60
+ export default function createStoreContext <
61
+ TState ,
62
+ TContexts extends Contexts ,
63
+ TActions extends Actions < TState , TContexts > = { } ,
64
+ > (
65
+ initialState : TState ,
66
+ actions : TActions = { } as TActions ,
67
+ contexts : TContexts = { } as TContexts
68
+ ) : [ React . Context < Store < TState , TContexts , TActions > > , React . FC ] {
69
+ // tslint:disable-next-line: max-line-length
70
+ const store = { ...initialState , ...mapActionsToDefault ( initialState , actions ) } as Store < TState , TContexts , TActions >
53
71
const context = React . createContext ( store )
54
72
55
73
const provider : React . FC = props => {
56
74
let [ _state , setState ] = React . useState ( initialState )
75
+
76
+ const stores = Object . keys ( contexts ) . reduce (
77
+ ( obj , key ) => {
78
+ return {
79
+ ...obj ,
80
+ [ key ] : React . useContext ( contexts [ key ] )
81
+ }
82
+ } ,
83
+ { } as InferStores < TContexts > )
84
+
57
85
const _actions = mapActionsToDispatch ( {
58
86
state : _state ,
59
- setState
87
+ setState,
88
+ stores
60
89
} , actions )
61
90
62
- const _store = { ..._state , ..._actions } as Store < TState , TActions >
91
+ const _store = { ..._state , ..._actions } as Store < TState , TContexts , TActions >
63
92
64
93
return (
65
94
< context . Provider value = { _store } >
@@ -71,37 +100,42 @@ export default function createStoreContext<TState, TActions extends Actions<TSta
71
100
return [ context , provider ]
72
101
}
73
102
74
- function mapActionsToDispatch < TState , TActions extends Actions < TState > > (
75
- contextReference : ContextReference < TState > ,
103
+ function mapActionsToDispatch < TState , TContexts extends Contexts , TActions extends Actions < TState , TContexts > > (
104
+ contextReference : ContextReference < TState , TContexts > ,
76
105
actions ?: TActions ,
77
- ) : MappedActions < TState , TActions > {
78
- if ( actions === undefined ) return { } as MappedActions < TState , TActions >
106
+ ) : MappedActions < TState , TContexts , TActions > {
107
+ if ( actions === undefined ) return { } as MappedActions < TState , TContexts , TActions >
79
108
return Object . keys ( actions ) . reduce (
80
109
( obj , key ) => {
81
110
return {
82
111
...obj ,
83
112
[ key ] : ( ...args : never [ ] ) => actions [ key ] ( contextReference , ...args )
84
113
}
85
114
} ,
86
- { } as MappedActions < TState , TActions > )
115
+ { } as MappedActions < TState , TContexts , TActions > )
87
116
}
88
117
89
- function mapActionsToDefault < TState , TActions extends Actions < TState > > (
118
+ function mapActionsToDefault < TState ,
119
+ TActions extends Actions < TState , TContexts > ,
120
+ TContexts extends Contexts
121
+ > (
90
122
initialState : TState ,
91
123
actions ?: TActions ,
92
- ) : MappedActions < TState , TActions > {
93
- if ( actions === undefined ) return { } as MappedActions < TState , TActions >
124
+ ) : MappedActions < TState , TContexts , TActions > {
125
+ if ( actions === undefined ) return { } as MappedActions < TState , TContexts , TActions >
94
126
95
127
return Object . keys ( actions ) . reduce (
96
128
( obj , key ) => {
97
- const contextReference : ContextReference < TState > = {
129
+ const contextReference : ContextReference < TState , TContexts > = {
98
130
state : initialState ,
131
+ stores : { } as InferStores < TContexts > ,
132
+ // tslint:disable-next-line: max-line-length
99
133
setState : ( value ) => { throw new Error ( `[${ key } ]: Can't invoke 'setState' with ${ value } because provider does not exist` ) }
100
134
}
101
135
return {
102
136
...obj ,
103
137
[ key ] : ( ...args : never [ ] ) => actions [ key ] ( contextReference , ...args )
104
138
}
105
139
} ,
106
- { } as MappedActions < TState , TActions > )
140
+ { } as MappedActions < TState , TContexts , TActions > )
107
141
}
0 commit comments