Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary
The main change to pay attention to here is the update to the
Reducer
type. Before this PRReducer
has a type of:After this PR
Reducer
has this type:Explanation
Why the need for this change? When the store is first created by
createStore
, the initial state is set to whatever is passed as thepreloadedState
argument (orundefined
if nothing is passed). That means that the first time that the reducer is called, it is called with thepreloadedState
. After the first call, the reducer is always passed the current state (which isS
).For most normal reducers,
S | undefined
accurately describes what can be passed in for thepreloadedState
. However thecombineReducers
function allows for a preloaded state ofPartial<S> | undefined
.The solution is to have a separate generic that represents what the reducer accepts for its preloaded state. That way
createStore
can then use that generic for itspreloadedState
argument.Previous work
Up until now, this has been accounted for with the
$CombinedState
type which is a way to "mark" a type as returned bycombineReducers
. ThePreloadedState
type then looks to see if the type has that "mark" and then acceptsPartial<S>
if it has that "mark."One of the problems this can cause is that if there are multiple copies of Redux in
node_modules
, then the "mark" for one copy of Redux is different than the "mark" for the other copy, and therefore they won't recognize each other.This also seems to be causing some problems in reduxjs/redux-toolkit#2068.
This PR removes the need for
$CombinedState
altogether.Upgrade Impact
This change does include some breaking changes, but overall should not have a huge impact on users upgrading in user-land.
Additional generic arguments
The
Reducer
,ReducersMapObject
, andcreateStore
types/function take an additionalPreloadedState
generic which defaults toS
.combineReducers
The overloads for
combineReducers
are removed in favor of a single function definition that takes theReducersMabObject
as its generic parameter. Removing the overloads was necessary with these changes, since sometimes it was choosing the wrong overload.Enhancers
Enhancers that explicitly list the generics for the reducer will need to add the third generic.