Skip to content

Commit da97831

Browse files
committed
Fix configureStore() state type inference edge case
When passing an object as `reducer` and at the same time `preloadedState`, TypeScript infers the store state type from the latter although `preloadedState` is potentially just a partial state. An additional `PS` type parameter fixes this.
1 parent 3933c9a commit da97831

File tree

2 files changed

+34
-6
lines changed

2 files changed

+34
-6
lines changed

src/configureStore.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,11 @@ export function getDefaultMiddleware(
4747
/**
4848
* Options for `configureStore()`.
4949
*/
50-
export interface ConfigureStoreOptions<S = any, A extends Action = AnyAction> {
50+
export interface ConfigureStoreOptions<
51+
S = any,
52+
A extends Action = AnyAction,
53+
PS extends S = S
54+
> {
5155
/**
5256
* A single reducer function that will be used as the root reducer, or an
5357
* object of slice reducers that will be passed to `combineReducers()`.
@@ -72,7 +76,7 @@ export interface ConfigureStoreOptions<S = any, A extends Action = AnyAction> {
7276
* function (either directly or indirectly by passing an object as `reducer`),
7377
* this must be an object with the same shape as the reducer map keys.
7478
*/
75-
preloadedState?: DeepPartial<S>
79+
preloadedState?: DeepPartial<PS>
7680

7781
/**
7882
* The store enhancers to apply. See Redux's `createStore()`. If you only
@@ -87,9 +91,11 @@ export interface ConfigureStoreOptions<S = any, A extends Action = AnyAction> {
8791
* @param config The store configuration.
8892
* @returns A configured Redux store.
8993
*/
90-
export function configureStore<S = any, A extends Action = AnyAction>(
91-
options: ConfigureStoreOptions<S, A>
92-
): Store<S, A> {
94+
export function configureStore<
95+
S = any,
96+
A extends Action = AnyAction,
97+
PS extends S = S
98+
>(options: ConfigureStoreOptions<S, A, PS>): Store<S, A> {
9399
const {
94100
reducer = undefined,
95101
middleware = getDefaultMiddleware(),
@@ -132,7 +138,7 @@ export function configureStore<S = any, A extends Action = AnyAction>(
132138

133139
const store: Store<S, A> = createStore(
134140
rootReducer,
135-
preloadedState,
141+
preloadedState as DeepPartial<S>,
136142
composedEnhancer
137143
)
138144

type-tests/files/configureStore.typetest.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,25 @@ import {
122122
enhancers: ['not a store enhancer']
123123
})
124124
}
125+
126+
/**
127+
* Test: configureStore() state type inference works when specifying both a
128+
* reducer object and a partial preloaded state.
129+
*/
130+
{
131+
let counterReducer1: Reducer<number> = () => 0
132+
let counterReducer2: Reducer<number> = () => 0
133+
134+
const store = configureStore({
135+
reducer: {
136+
counter1: counterReducer1,
137+
counter2: counterReducer2
138+
},
139+
preloadedState: {
140+
counter1: 0
141+
}
142+
})
143+
144+
const counter1: number = store.getState().counter1
145+
const counter2: number = store.getState().counter2
146+
}

0 commit comments

Comments
 (0)