1
- import { Store } from "./store" ;
1
+ import { Store , Dispatch } from "./store" ;
2
2
import * as React from "react" ;
3
3
import { Subscription } from "rxjs" ;
4
4
import { Reducers } from "./reducer" ;
5
- import { PayloadOfActionCreator } from "./action" ;
5
+ import { ActionCreator } from "./action" ;
6
6
7
7
type Omit < T , K extends keyof T > = Pick < T , Exclude < keyof T , K > > ;
8
-
9
- type MapActionProps < TActionProps > = { [ K in keyof TActionProps ] : ( payload : PayloadOfActionCreator < TActionProps [ K ] > ) => void } ;
10
-
11
8
type SelectorProps < TState > = { [ key : string ] : ( state : TState ) => unknown } ;
9
+ type ActionProps = { [ key : string ] : ActionCreator < string , unknown > } ;
12
10
13
- const mapSelectorProps = < TState , TStateProps extends SelectorProps < TState > > ( state : TState , stateProps : TStateProps ) => {
14
- const props : any = { } ;
15
-
16
- for ( const key in stateProps ) {
17
- const selector = stateProps [ key ] ;
18
- props [ key ] = selector ( state ) ;
19
- }
20
-
21
- return props ;
11
+ const mapSelectorProps = < TState , TSelectorProps extends SelectorProps < TState > , TProps , TSelectorKeys extends keyof TProps > (
12
+ state : TState ,
13
+ selectorProps : TSelectorProps ,
14
+ ) => {
15
+ const stateProps = Object . keys ( selectorProps ) . reduce (
16
+ ( stateProps , key ) => {
17
+ stateProps [ key ] = selectorProps [ key ] ( state ) ;
18
+ return stateProps ;
19
+ } ,
20
+ { } as Pick < TProps , TSelectorKeys > ,
21
+ ) ;
22
+ return stateProps ;
22
23
} ;
23
24
24
- const mapActionProps = < TState , TReducers , TActionProps > ( store : Store < TState , TReducers > , actionProps : TActionProps ) => {
25
- const dispatchProps : any = { } ;
26
-
27
- for ( const key in actionProps ) {
28
- dispatchProps [ key ] = ( payload ) => {
29
- const action = ( actionProps [ key ] as any ) ( payload ) ;
30
- store . dispatch ( action as any ) ;
31
- } ;
32
- }
25
+ const mapActionProps = < TState , TReducers , TActionProps , TProps , TActionKeys extends keyof TProps > (
26
+ store : Store < TState , TReducers > ,
27
+ actionProps : TActionProps ,
28
+ ) => {
29
+ const dispatchProps = Object . keys ( actionProps ) . reduce (
30
+ ( dispatchProps , key ) => {
31
+ dispatchProps [ key ] = ( payload ) => store . dispatch ( actionProps [ key ] ( payload ) ) ;
32
+ return dispatchProps ;
33
+ } ,
34
+ { } as Pick < TProps , TActionKeys > ,
35
+ ) ;
33
36
34
37
return dispatchProps ;
35
38
} ;
36
39
37
40
export const connect = < TState , TReducers extends Reducers < TState > > ( store : Store < TState , TReducers > ) => <
38
41
TSelectorProps extends SelectorProps < TState > ,
39
- TActionProps
42
+ TActionProps extends ActionProps
40
43
> (
41
44
stateProps : TSelectorProps ,
42
45
actionProps : TActionProps ,
43
46
) => <
44
- TProps extends Pick < TProps , keyof TSelectorProps > & MapActionProps < TActionProps > ,
47
+ TProps extends Pick < TProps , keyof TSelectorProps > & Pick < TProps , keyof TActionProps > ,
45
48
ExternalProps = Omit < TProps , keyof TSelectorProps | keyof TActionProps >
46
49
> (
47
50
Component : React . ComponentType < TProps > ,
48
51
) : React . ComponentType < ExternalProps > => {
49
- const dispatchProps = mapActionProps ( store , actionProps ) ;
52
+ const dispatchProps = mapActionProps < TState , TReducers , TActionProps , TProps , keyof TActionProps > ( store , actionProps ) ;
50
53
51
54
return class extends React . Component < ExternalProps , { subscription : Subscription ; stateProps : Pick < TProps , keyof TSelectorProps > } > {
52
55
public constructor ( props : ExternalProps ) {
@@ -56,7 +59,7 @@ export const connect = <TState, TReducers extends Reducers<TState>>(store: Store
56
59
public componentDidMount ( ) : void {
57
60
store . state$ . subscribe ( ( state ) => {
58
61
this . setState ( {
59
- stateProps : mapSelectorProps ( state , stateProps ) ,
62
+ stateProps : mapSelectorProps < TState , TSelectorProps , TProps , keyof TSelectorProps > ( state , stateProps ) ,
60
63
} ) ;
61
64
} ) ;
62
65
}
@@ -68,7 +71,9 @@ export const connect = <TState, TReducers extends Reducers<TState>>(store: Store
68
71
}
69
72
70
73
public render ( ) : JSX . Element {
71
- const WrappedComponent = ( Component as unknown ) as React . ComponentType < ExternalProps & Pick < TProps , keyof TSelectorProps > & MapActionProps < TActionProps > > ;
74
+ const WrappedComponent = ( Component as unknown ) as React . ComponentType <
75
+ ExternalProps & Pick < TProps , keyof TSelectorProps > & Pick < TProps , keyof TActionProps >
76
+ > ;
72
77
return this . state && < WrappedComponent { ...this . props } { ...this . state . stateProps } { ...dispatchProps } /> ;
73
78
}
74
79
} ;
0 commit comments