Skip to content

Commit

Permalink
fix PreloadedState type for TS 4.3 (#949)
Browse files Browse the repository at this point in the history
  • Loading branch information
phryneas committed Mar 28, 2021
1 parent f98b9b2 commit 9abaec4
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 11 deletions.
5 changes: 3 additions & 2 deletions etc/redux-toolkit.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
import { Action } from 'redux';
import { ActionCreator } from 'redux';
import { AnyAction } from 'redux';
import { CombinedState } from 'redux';
import { default as createNextState } from 'immer';
import { createSelector } from 'reselect';
import { current } from 'immer';
import { DeepPartial } from 'redux';
import { Dispatch } from 'redux';
import { Draft } from 'immer';
import { freeze } from 'immer';
Expand All @@ -20,6 +20,7 @@ import { original } from 'immer';
import { OutputParametricSelector } from 'reselect';
import { OutputSelector } from 'reselect';
import { ParametricSelector } from 'reselect';
import { PreloadedState } from 'redux';
import { Reducer } from 'redux';
import { ReducersMapObject } from 'redux';
import { Selector } from 'reselect';
Expand Down Expand Up @@ -127,7 +128,7 @@ export interface ConfigureStoreOptions<S = any, A extends Action = AnyAction, M
devTools?: boolean | EnhancerOptions;
enhancers?: StoreEnhancer[] | ConfigureEnhancersCallback;
middleware?: ((getDefaultMiddleware: CurriedGetDefaultMiddleware<S>) => M) | M;
preloadedState?: DeepPartial<S extends any ? S : S>;
preloadedState?: PreloadedState<CombinedState<NoInfer<S>>>;
reducer: Reducer<S, A> | ReducersMapObject<S, A>;
}

Expand Down
24 changes: 15 additions & 9 deletions src/configureStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ import {
AnyAction,
StoreEnhancer,
Store,
DeepPartial,
Dispatch
Dispatch,
PreloadedState,
CombinedState
} from 'redux'
import {
composeWithDevTools,
Expand All @@ -24,7 +25,7 @@ import {
curryGetDefaultMiddleware,
CurriedGetDefaultMiddleware
} from './getDefaultMiddleware'
import { DispatchForMiddlewares } from './tsHelpers'
import { DispatchForMiddlewares, NoInfer } from './tsHelpers'

const IS_PRODUCTION = process.env.NODE_ENV === 'production'

Expand Down Expand Up @@ -74,11 +75,16 @@ export interface ConfigureStoreOptions<
* function (either directly or indirectly by passing an object as `reducer`),
* this must be an object with the same shape as the reducer map keys.
*/
// NOTE: The needlessly complicated `S extends any ? S : S` instead of just
// `S` ensures that the TypeScript compiler doesn't attempt to infer `S`
// based on the value passed as `preloadedState`, which might be a partial
// state rather than the full thing.
preloadedState?: DeepPartial<S extends any ? S : S>
/*
Not 100% correct but the best approximation we can get:
- if S is a `CombinedState` applying a second `CombinedState` on it does not change anything.
- if it is not, there could be two cases:
- `ReducersMapObject<S, A>` is being passed in. In this case, we will call `combineReducers` on it and `CombinedState<S>` is correct
- `Reducer<S, A>` is being passed in. In this case, actually `CombinedState<S>` is wrong and `S` would be correct.
As we cannot distinguish between those two cases without adding another generic paramter,
we just make the pragmatic assumption that the latter almost never happens.
*/
preloadedState?: PreloadedState<CombinedState<NoInfer<S>>>

/**
* The store enhancers to apply. See Redux's `createStore()`.
Expand Down Expand Up @@ -173,5 +179,5 @@ export function configureStore<

const composedEnhancer = finalCompose(...storeEnhancers) as any

return createStore(rootReducer, preloadedState as any, composedEnhancer)
return createStore(rootReducer, preloadedState, composedEnhancer)
}

0 comments on commit 9abaec4

Please sign in to comment.