@@ -68,10 +68,21 @@ function discriminated() {
68
68
count ?: number
69
69
}
70
70
71
+ interface MultiplyAction {
72
+ type : 'MULTIPLY'
73
+ count ?: number
74
+ }
75
+
76
+ interface DivideAction {
77
+ type : 'DIVIDE'
78
+ count ?: number
79
+ }
80
+
71
81
// Union of all actions in the app.
72
- type MyAction = IncrementAction | DecrementAction
82
+ type MyAction0 = IncrementAction | DecrementAction
83
+ type MyAction1 = MultiplyAction | DivideAction
73
84
74
- const reducer : Reducer < State , MyAction > = ( state = 0 , action ) => {
85
+ const reducer0 : Reducer < State , MyAction0 > = ( state = 0 , action ) => {
75
86
if ( action . type === 'INCREMENT' ) {
76
87
// Action shape is determined by `type` discriminator.
77
88
// typings:expect-error
@@ -94,37 +105,65 @@ function discriminated() {
94
105
return state
95
106
}
96
107
108
+ const reducer1 : Reducer < State , MyAction1 > = ( state = 0 , action ) => {
109
+ if ( action . type === 'MULTIPLY' ) {
110
+ // typings:expect-error
111
+ action . wrongField
112
+
113
+ const { count = 1 } = action
114
+
115
+ return state * count
116
+ }
117
+
118
+ if ( action . type === 'DIVIDE' ) {
119
+ // typings:expect-error
120
+ action . wrongField
121
+
122
+ const { count = 1 } = action
123
+
124
+ return state / count
125
+ }
126
+
127
+ return state
128
+ }
129
+
97
130
// Reducer state is initialized by Redux using Init action which is private.
98
131
// To initialize manually (e.g. in tests) we have to type cast init action
99
132
// or add a custom init action to MyAction union.
100
- let s : State = reducer ( undefined , { type : 'init' } as any )
101
- s = reducer ( s , { type : 'INCREMENT' } )
102
- s = reducer ( s , { type : 'INCREMENT' , count : 10 } )
133
+ let s : State = reducer0 ( undefined , { type : 'init' } as any )
134
+ s = reducer0 ( s , { type : 'INCREMENT' } )
135
+ s = reducer0 ( s , { type : 'INCREMENT' , count : 10 } )
103
136
// Known actions are strictly checked.
104
137
// typings:expect-error
105
- s = reducer ( s , { type : 'DECREMENT' , coun : 10 } )
106
- s = reducer ( s , { type : 'DECREMENT' , count : 10 } )
138
+ s = reducer0 ( s , { type : 'DECREMENT' , coun : 10 } )
139
+ s = reducer0 ( s , { type : 'DECREMENT' , count : 10 } )
107
140
// Unknown actions are rejected.
108
141
// typings:expect-error
109
- s = reducer ( s , { type : 'SOME_OTHER_TYPE' } )
142
+ s = reducer0 ( s , { type : 'SOME_OTHER_TYPE' } )
110
143
// typings:expect-error
111
- s = reducer ( s , { type : 'SOME_OTHER_TYPE' , someField : 'value' } )
144
+ s = reducer0 ( s , { type : 'SOME_OTHER_TYPE' , someField : 'value' } )
112
145
113
- // Combined reducer accepts any action by default which allows to include
114
- // third-party reducers without the need to add their actions to the union.
115
- const combined = combineReducers ( { sub : reducer } )
146
+ // Combined reducer infers state and actions by default which maintains type
147
+ // safety and still allows inclusion of third-party reducers without the need
148
+ // to explicitly add their state and actions to the union.
149
+ const combined = combineReducers ( { sub0 : reducer0 , sub1 : reducer1 } )
116
150
117
- let cs : { sub : State } = combined ( undefined , { type : 'init' } )
118
- cs = combined ( cs , { type : 'SOME_OTHER_TYPE' } )
151
+ const cs = combined ( undefined , { type : 'INCREMENT' } )
152
+ combined ( cs , { type : 'MULTIPLY' } )
153
+ // typings:expect-error
154
+ combined ( cs , { type : 'init' } )
155
+ // typings:expect-error
156
+ combined ( cs , { type : 'SOME_OTHER_TYPE' } )
119
157
120
158
// Combined reducer can be made to only accept known actions.
121
- const strictCombined = combineReducers < { sub : State } , MyAction > ( {
122
- sub : reducer
159
+ const strictCombined = combineReducers < { sub : State } , MyAction0 > ( {
160
+ sub : reducer0
123
161
} )
124
162
125
- strictCombined ( cs , { type : 'INCREMENT' } )
163
+ const scs = strictCombined ( undefined , { type : 'INCREMENT' } )
164
+ strictCombined ( scs , { type : 'DECREMENT' } )
126
165
// typings:expect-error
127
- strictCombined ( cs , { type : 'SOME_OTHER_TYPE' } )
166
+ strictCombined ( scs , { type : 'SOME_OTHER_TYPE' } )
128
167
}
129
168
130
169
/**
0 commit comments