Skip to content

Commit 1c21c86

Browse files
committed
Introduce EnhancedStore type for thunk dispatch
1 parent 7b0502d commit 1c21c86

File tree

2 files changed

+38
-11
lines changed

2 files changed

+38
-11
lines changed

src/configureStore.ts

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@ import {
1010
AnyAction,
1111
StoreEnhancer,
1212
Store,
13-
DeepPartial
13+
DeepPartial,
14+
Dispatch
1415
} from 'redux'
1516
import { composeWithDevTools } from 'redux-devtools-extension'
16-
import thunk from 'redux-thunk'
17+
import thunk, { ThunkDispatch, ThunkMiddleware } from 'redux-thunk'
1718
import createImmutableStateInvariantMiddleware from 'redux-immutable-state-invariant'
1819
import createSerializableStateInvariantMiddleware from './serializableStateInvariantMiddleware'
1920

@@ -28,10 +29,10 @@ const IS_PRODUCTION = process.env.NODE_ENV === 'production'
2829
*
2930
* @return The default middleware used by `configureStore()`.
3031
*/
31-
export function getDefaultMiddleware(
32+
export function getDefaultMiddleware<S = any, A extends Action = AnyAction>(
3233
isProduction = IS_PRODUCTION
33-
): Middleware[] {
34-
let middlewareArray: Middleware[] = [thunk]
34+
): [ThunkMiddleware<S, A>, ...Middleware<{}, S>[]] {
35+
let middlewareArray: [ThunkMiddleware<S, A>, ...Middleware<{}, S>[]] = [thunk]
3536

3637
if (!isProduction) {
3738
middlewareArray = [
@@ -58,7 +59,7 @@ export interface ConfigureStoreOptions<S = any, A extends Action = AnyAction> {
5859
* An array of Redux middleware to install. If not supplied, defaults to
5960
* the set of middleware returned by `getDefaultMiddleware()`.
6061
*/
61-
middleware?: Middleware[]
62+
middleware?: Middleware<{}, S>[]
6263

6364
/**
6465
* Whether to enable Redux DevTools integration. Defaults to `true`.
@@ -85,6 +86,15 @@ export interface ConfigureStoreOptions<S = any, A extends Action = AnyAction> {
8586
enhancers?: StoreEnhancer[]
8687
}
8788

89+
/**
90+
* A Redux store returned by `configureStore()`. Supports dispatching
91+
* side-effectful _thunks_ in addition to plain actions.
92+
*/
93+
export interface EnhancedStore<S = any, A extends Action = AnyAction>
94+
extends Store<S, A> {
95+
dispatch: ThunkDispatch<S, any, A>
96+
}
97+
8898
/**
8999
* A friendly abstraction over the standard Redux `createStore()` function.
90100
*
@@ -93,7 +103,7 @@ export interface ConfigureStoreOptions<S = any, A extends Action = AnyAction> {
93103
*/
94104
export function configureStore<S = any, A extends Action = AnyAction>(
95105
options: ConfigureStoreOptions<S, A>
96-
): Store<S, A> {
106+
): EnhancedStore<S, A> {
97107
const {
98108
reducer = undefined,
99109
middleware = getDefaultMiddleware(),
@@ -134,11 +144,9 @@ export function configureStore<S = any, A extends Action = AnyAction>(
134144

135145
const composedEnhancer = finalCompose(...storeEnhancers) as StoreEnhancer
136146

137-
const store: Store<S, A> = createStore(
147+
return createStore(
138148
rootReducer,
139149
preloadedState as DeepPartial<S>,
140150
composedEnhancer
141151
)
142-
143-
return store
144152
}

type-tests/files/configureStore.typetest.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { applyMiddleware } from 'redux'
1+
import { applyMiddleware, Dispatch } from 'redux'
22
import {
33
AnyAction,
44
configureStore,
@@ -144,3 +144,22 @@ import {
144144
const counter1: number = store.getState().counter1
145145
const counter2: number = store.getState().counter2
146146
}
147+
148+
/**
149+
* Test: Returned store allows dispatching thunks.
150+
*/
151+
{
152+
const store = configureStore({
153+
reducer: () => 0
154+
})
155+
156+
function incrementMaybe() {
157+
return (dispatch: Dispatch) => {
158+
if (Math.random() > 0.5) {
159+
dispatch({ type: 'increment' })
160+
}
161+
}
162+
}
163+
164+
store.dispatch(incrementMaybe())
165+
}

0 commit comments

Comments
 (0)