Skip to content

Commit a5e4f95

Browse files
authored
Merge pull request #3772 from Methuselah96/replace-reducer-rebase
resolves #3767 resolves #3482
2 parents 5c6d100 + 8edc1ff commit a5e4f95

File tree

7 files changed

+77
-118
lines changed

7 files changed

+77
-118
lines changed

src/createStore.ts

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import {
66
StoreEnhancer,
77
Dispatch,
88
Observer,
9-
ExtendState,
109
ListenerCallback
1110
} from './types/store'
1211
import { Action } from './types/actions'
@@ -43,7 +42,7 @@ import { kindOf } from './utils/kindOf'
4342
export function createStore<S, A extends Action, Ext = {}, StateExt = never>(
4443
reducer: Reducer<S, A>,
4544
enhancer?: StoreEnhancer<Ext, StateExt>
46-
): Store<ExtendState<S, StateExt>, A, StateExt, Ext> & Ext
45+
): Store<S, A, StateExt> & Ext
4746
/**
4847
* @deprecated
4948
*
@@ -73,12 +72,12 @@ export function createStore<S, A extends Action, Ext = {}, StateExt = never>(
7372
reducer: Reducer<S, A>,
7473
preloadedState?: PreloadedState<S>,
7574
enhancer?: StoreEnhancer<Ext, StateExt>
76-
): Store<ExtendState<S, StateExt>, A, StateExt, Ext> & Ext
75+
): Store<S, A, StateExt> & Ext
7776
export function createStore<S, A extends Action, Ext = {}, StateExt = never>(
7877
reducer: Reducer<S, A>,
7978
preloadedState?: PreloadedState<S> | StoreEnhancer<Ext, StateExt>,
8079
enhancer?: StoreEnhancer<Ext, StateExt>
81-
): Store<ExtendState<S, StateExt>, A, StateExt, Ext> & Ext {
80+
): Store<S, A, StateExt> & Ext {
8281
if (typeof reducer !== 'function') {
8382
throw new Error(
8483
`Expected the root reducer to be a function. Instead, received: '${kindOf(
@@ -115,7 +114,7 @@ export function createStore<S, A extends Action, Ext = {}, StateExt = never>(
115114
return enhancer(createStore)(
116115
reducer,
117116
preloadedState as PreloadedState<S>
118-
) as Store<ExtendState<S, StateExt>, A, StateExt, Ext> & Ext
117+
) as Store<S, A, StateExt> & Ext
119118
}
120119

121120
let currentReducer = reducer
@@ -291,11 +290,8 @@ export function createStore<S, A extends Action, Ext = {}, StateExt = never>(
291290
* implement a hot reloading mechanism for Redux.
292291
*
293292
* @param nextReducer The reducer for the store to use instead.
294-
* @returns The same store instance with a new reducer in place.
295293
*/
296-
function replaceReducer<NewState, NewActions extends A>(
297-
nextReducer: Reducer<NewState, NewActions>
298-
): Store<ExtendState<NewState, StateExt>, NewActions, StateExt, Ext> & Ext {
294+
function replaceReducer(nextReducer: Reducer<S, A>): void {
299295
if (typeof nextReducer !== 'function') {
300296
throw new Error(
301297
`Expected the nextReducer to be a function. Instead, received: '${kindOf(
@@ -304,22 +300,13 @@ export function createStore<S, A extends Action, Ext = {}, StateExt = never>(
304300
)
305301
}
306302

307-
// TODO: do this more elegantly
308-
;(currentReducer as unknown as Reducer<NewState, NewActions>) = nextReducer
303+
currentReducer = nextReducer
309304

310305
// This action has a similar effect to ActionTypes.INIT.
311306
// Any reducers that existed in both the new and old rootReducer
312307
// will receive the previous state. This effectively populates
313308
// the new state tree with any relevant data from the old one.
314309
dispatch({ type: ActionTypes.REPLACE } as A)
315-
// change the type of the store by casting it to the new store
316-
return store as unknown as Store<
317-
ExtendState<NewState, StateExt>,
318-
NewActions,
319-
StateExt,
320-
Ext
321-
> &
322-
Ext
323310
}
324311

325312
/**
@@ -377,7 +364,7 @@ export function createStore<S, A extends Action, Ext = {}, StateExt = never>(
377364
getState,
378365
replaceReducer,
379366
[$$observable]: observable
380-
} as unknown as Store<ExtendState<S, StateExt>, A, StateExt, Ext> & Ext
367+
} as unknown as Store<S, A, StateExt> & Ext
381368
return store
382369
}
383370

@@ -419,7 +406,7 @@ export function legacy_createStore<
419406
>(
420407
reducer: Reducer<S, A>,
421408
enhancer?: StoreEnhancer<Ext, StateExt>
422-
): Store<ExtendState<S, StateExt>, A, StateExt, Ext> & Ext
409+
): Store<S, A, StateExt> & Ext
423410
/**
424411
* Creates a Redux store that holds the state tree.
425412
*
@@ -459,7 +446,7 @@ export function legacy_createStore<
459446
reducer: Reducer<S, A>,
460447
preloadedState?: PreloadedState<S>,
461448
enhancer?: StoreEnhancer<Ext, StateExt>
462-
): Store<ExtendState<S, StateExt>, A, StateExt, Ext> & Ext
449+
): Store<S, A, StateExt> & Ext
463450
export function legacy_createStore<
464451
S,
465452
A extends Action,
@@ -469,6 +456,6 @@ export function legacy_createStore<
469456
reducer: Reducer<S, A>,
470457
preloadedState?: PreloadedState<S> | StoreEnhancer<Ext, StateExt>,
471458
enhancer?: StoreEnhancer<Ext, StateExt>
472-
): Store<ExtendState<S, StateExt>, A, StateExt, Ext> & Ext {
459+
): Store<S, A, StateExt> & Ext {
473460
return createStore(reducer, preloadedState as any, enhancer)
474461
}

src/types/store.ts

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -133,13 +133,11 @@ export type Observer<T> = {
133133
* @template S The type of state held by this store.
134134
* @template A the type of actions which may be dispatched by this store.
135135
* @template StateExt any extension to state from store enhancers
136-
* @template Ext any extensions to the store from store enhancers
137136
*/
138137
export interface Store<
139138
S = any,
140139
A extends Action = AnyAction,
141-
StateExt = never,
142-
Ext = {}
140+
StateExt = never
143141
> {
144142
/**
145143
* Dispatches an action. It is the only way to trigger a state change.
@@ -174,7 +172,7 @@ export interface Store<
174172
*
175173
* @returns The current state tree of your application.
176174
*/
177-
getState(): S
175+
getState(): ExtendState<S, StateExt>
178176

179177
/**
180178
* Adds a change listener. It will be called any time an action is
@@ -211,17 +209,15 @@ export interface Store<
211209
*
212210
* @param nextReducer The reducer for the store to use instead.
213211
*/
214-
replaceReducer<NewState, NewActions extends Action>(
215-
nextReducer: Reducer<NewState, NewActions>
216-
): Store<ExtendState<NewState, StateExt>, NewActions, StateExt, Ext> & Ext
212+
replaceReducer(nextReducer: Reducer<S, A>): void
217213

218214
/**
219215
* Interoperability point for observable/reactive libraries.
220216
* @returns {observable} A minimal observable of state changes.
221217
* For more information, see the observable proposal:
222218
* https://github.com/tc39/proposal-observable
223219
*/
224-
[Symbol.observable](): Observable<S>
220+
[Symbol.observable](): Observable<ExtendState<S, StateExt>>
225221
}
226222

227223
/**
@@ -239,12 +235,12 @@ export interface StoreCreator {
239235
<S, A extends Action, Ext = {}, StateExt = never>(
240236
reducer: Reducer<S, A>,
241237
enhancer?: StoreEnhancer<Ext, StateExt>
242-
): Store<ExtendState<S, StateExt>, A, StateExt, Ext> & Ext
238+
): Store<S, A, StateExt> & Ext
243239
<S, A extends Action, Ext = {}, StateExt = never>(
244240
reducer: Reducer<S, A>,
245241
preloadedState?: PreloadedState<S>,
246242
enhancer?: StoreEnhancer<Ext>
247-
): Store<ExtendState<S, StateExt>, A, StateExt, Ext> & Ext
243+
): Store<S, A, StateExt> & Ext
248244
}
249245

250246
/**
@@ -277,4 +273,4 @@ export type StoreEnhancerStoreCreator<Ext = {}, StateExt = never> = <
277273
>(
278274
reducer: Reducer<S, A>,
279275
preloadedState?: PreloadedState<S>
280-
) => Store<ExtendState<S, StateExt>, A, StateExt, Ext> & Ext
276+
) => Store<S, A, StateExt> & Ext

test/combineReducers.spec.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -327,31 +327,35 @@ describe('Utils', () => {
327327
const ACTION = { type: 'ACTION' }
328328

329329
it('should return an updated state when additional reducers are passed to combineReducers', function () {
330-
const originalCompositeReducer = combineReducers({ foo })
330+
type State = { foo: {}; bar?: {} }
331+
332+
const originalCompositeReducer = combineReducers<State>({ foo })
331333
const store = createStore(originalCompositeReducer)
332334

333335
store.dispatch(ACTION)
334336

335337
const initialState = store.getState()
336338

337-
store.replaceReducer(combineReducers({ foo, bar }))
339+
store.replaceReducer(combineReducers<State>({ foo, bar }))
338340
store.dispatch(ACTION)
339341

340342
const nextState = store.getState()
341343
expect(nextState).not.toBe(initialState)
342344
})
343345

344346
it('should return an updated state when reducers passed to combineReducers are changed', function () {
347+
type State = { foo?: {}; bar: {}; baz?: {} }
348+
345349
const baz = (state = {}) => state
346350

347-
const originalCompositeReducer = combineReducers({ foo, bar })
351+
const originalCompositeReducer = combineReducers<State>({ foo, bar })
348352
const store = createStore(originalCompositeReducer)
349353

350354
store.dispatch(ACTION)
351355

352356
const initialState = store.getState()
353357

354-
store.replaceReducer(combineReducers({ baz, bar }))
358+
store.replaceReducer(combineReducers<State>({ baz, bar }))
355359
store.dispatch(ACTION)
356360

357361
const nextState = store.getState()
@@ -374,7 +378,9 @@ describe('Utils', () => {
374378
})
375379

376380
it('should return an updated state when one of more reducers passed to the combineReducers are removed', function () {
377-
const originalCompositeReducer = combineReducers({ foo, bar })
381+
const originalCompositeReducer = combineReducers<{ foo?: {}; bar: {} }>(
382+
{ foo, bar }
383+
)
378384
const store = createStore(originalCompositeReducer)
379385

380386
store.dispatch(ACTION)

test/createStore.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -824,7 +824,7 @@ describe('createStore', () => {
824824
console.error = jest.fn()
825825

826826
const store = createStore(
827-
combineReducers({
827+
combineReducers<{ x?: number; y: { z: number; w?: number } }>({
828828
x: (s = 0, _) => s,
829829
y: combineReducers({
830830
z: (s = 0, _) => s,

test/replaceReducers.spec.ts

Lines changed: 0 additions & 18 deletions
This file was deleted.

0 commit comments

Comments
 (0)