Skip to content

v5.0.0-alpha.5

Pre-release
Pre-release
Compare
Choose a tag to compare
@markerikson markerikson released this 16 Apr 19:41
· 236 commits to master since this release

This is an alpha release for Redux 5.0. This release has has breaking types changes.

npm i redux@alpha

yarn add redux@alpha

Changelog

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
) => S

Per 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, and createStore types/function take an additional PreloadedState generic which defaults to S.
  • The overloads for combineReducers are removed in favor of a single function definition that takes the ReducersMabObject as 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:

  • next would 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 next as the default Dispatch implemented by the base redux store, however this would cause next(action) to error (as we cannot promise action is actually an Action) - 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.
  • action is not necessarily a known action, it can be literally anything - for example a thunk would be a function with no .type property (so AnyAction would 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

Full Changelog: v5.0.0-alpha.4...v5.0.0-alpha.5