v5.0.0-alpha.5
Pre-releaseThis is an alpha release for Redux 5.0. This release has has breaking types changes.
npm i redux@alpha
yarn add redux@alphaChangelog
Reducer type and PreloadedState generic
We've made tweaks to the TS types to improve type safety and behavior. There are two big types changes in this alpha.
First, the Reducer type now has a PreloadedState possible generic:
type Reducer<S, A extends Action, PreloadedState = S> = (
state: S | PreloadedState | undefined,
action: A
) => SPer the explanation in #4491 :
Why the need for this change? When the store is first created by createStore, the initial state is set to whatever is passed as the preloadedState argument (or undefined if nothing is passed). That means that the first time that the reducer is called, it is called with the preloadedState. After the first call, the reducer is always passed the current state (which is S).
For most normal reducers, S | undefined accurately describes what can be passed in for the preloadedState. However the combineReducers function allows for a preloaded state of Partial<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 its preloadedState argument.
Previously, this was handled by a $CombinedState type, but that complicated things and led to some user-reported issues. This removes the need for $CombinedState altogether.
This change does include some breaking changes, but overall should not have a huge impact on users upgrading in user-land:
- The
Reducer,ReducersMapObject, andcreateStoretypes/function take an additionalPreloadedStategeneric which defaults toS. - The overloads for
combineReducersare removed in favor of a single function definition that takes theReducersMabObjectas its generic parameter. Removing the overloads was necessary with these changes, since sometimes it was choosing the wrong overload. - Enhancers that explicitly list the generics for the reducer will need to add the third generic.
Middleware action and next are typed as unknown
Currently, the next parameter is typed as the D type parameter passed, and action is typed as theAction extracted from the dispatch type. Neither of these are a safe assumption:
nextwould be typed to have all of the dispatch extensions, including the ones earlier in the chain that would no longer apply.- Technically it would be mostly safe to type
nextas the default Dispatch implemented by the base redux store, however this would causenext(action)to error (as we cannot promiseactionis actually anAction) - and it wouldn't account for any following middlewares that return anything other than the action they're given when they see a specific action.
- Technically it would be mostly safe to type
actionis not necessarily a known action, it can be literally anything - for example a thunk would be a function with no .type property (soAnyActionwould be inaccurate)
We've changed next to be (action: unknown) => unknown (which is accurate, we have no idea what next expects or will return), and changes the action parameter to be unknown (which as above, is accurate).
What's Changed
- Type-check tests by @Methuselah96 in #4489
- Add PreloadedState generic by @Methuselah96 in #4491
- Type action and next as unknown by @EskiMojo14 in #4519
Full Changelog: v5.0.0-alpha.4...v5.0.0-alpha.5