Skip to content

Commit 098353c

Browse files
author
ben.durrant
committed
Require usage of MiddlewareArray and EnhancerArray in TS
1 parent 44b4f67 commit 098353c

File tree

6 files changed

+96
-80
lines changed

6 files changed

+96
-80
lines changed

packages/toolkit/src/configureStore.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ const IS_PRODUCTION = process.env.NODE_ENV === 'production'
3737
export interface ConfigureStoreOptions<
3838
S = any,
3939
A extends Action = AnyAction,
40-
M extends Middlewares<S> = Middlewares<S>,
41-
E extends Enhancers = Enhancers,
40+
M extends MiddlewareArray<Middlewares<S>> = MiddlewareArray<Middlewares<S>>,
41+
E extends EnhancerArray<Enhancers> = EnhancerArray<Enhancers>,
4242
P = S
4343
> {
4444
/**
@@ -112,8 +112,10 @@ export type EnhancedStore<
112112
export function configureStore<
113113
S = any,
114114
A extends Action = AnyAction,
115-
M extends Middlewares<S> = MiddlewareArray<[ThunkMiddlewareFor<S>]>,
116-
E extends Enhancers = EnhancerArray<
115+
M extends MiddlewareArray<Middlewares<S>> = MiddlewareArray<
116+
[ThunkMiddlewareFor<S>]
117+
>,
118+
E extends EnhancerArray<Enhancers> = EnhancerArray<
117119
[StoreEnhancer<{ dispatch: ExtractDispatchExtensions<M> }>, StoreEnhancer]
118120
>,
119121
P = S

packages/toolkit/src/tests/configureStore.test.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { vi } from 'vitest'
2-
import type { StoreEnhancer, StoreEnhancerStoreCreator } from '@reduxjs/toolkit'
2+
import type { StoreEnhancer } from '@reduxjs/toolkit'
3+
import { MiddlewareArray, EnhancerArray } from '@reduxjs/toolkit'
34
import type * as Redux from 'redux'
45
import type * as DevTools from '@internal/devtoolsExtension'
56

@@ -108,7 +109,9 @@ describe('configureStore', async () => {
108109

109110
describe('given no middleware', () => {
110111
it('calls createStore without any middleware', () => {
111-
expect(configureStore({ middleware: [], reducer })).toBeInstanceOf(Object)
112+
expect(
113+
configureStore({ middleware: new MiddlewareArray(), reducer })
114+
).toBeInstanceOf(Object)
112115
expect(redux.applyMiddleware).toHaveBeenCalledWith()
113116
expect(mockDevtoolsCompose).toHaveBeenCalled() // @remap-prod-remove-line-line
114117
expect(redux.createStore).toHaveBeenCalledWith(
@@ -171,9 +174,9 @@ describe('configureStore', async () => {
171174
it('calls createStore with custom middleware and without default middleware', () => {
172175
const thank: Redux.Middleware = (_store) => (next) => (action) =>
173176
next(action)
174-
expect(configureStore({ middleware: [thank], reducer })).toBeInstanceOf(
175-
Object
176-
)
177+
expect(
178+
configureStore({ middleware: new MiddlewareArray(thank), reducer })
179+
).toBeInstanceOf(Object)
177180
expect(redux.applyMiddleware).toHaveBeenCalledWith(thank)
178181
expect(mockDevtoolsCompose).toHaveBeenCalled() // @remap-prod-remove-line-line
179182
expect(redux.createStore).toHaveBeenCalledWith(
@@ -194,7 +197,7 @@ describe('configureStore', async () => {
194197
expect(getDefaultMiddleware).toEqual(expect.any(Function))
195198
expect(getDefaultMiddleware()).toEqual(expect.any(Array))
196199

197-
return [thank]
200+
return new MiddlewareArray(thank)
198201
})
199202

200203
const store = configureStore({ middleware: builder, reducer })
@@ -303,7 +306,7 @@ describe('configureStore', async () => {
303306
it('warns if middleware enhancer is excluded from final array when middlewares are provided', () => {
304307
const store = configureStore({
305308
reducer,
306-
enhancers: [dummyEnhancer],
309+
enhancers: new EnhancerArray(dummyEnhancer),
307310
})
308311

309312
expect(dummyEnhancerCalled).toBe(true)
@@ -315,8 +318,8 @@ describe('configureStore', async () => {
315318
it("doesn't warn when middleware enhancer is excluded if no middlewares provided", () => {
316319
const store = configureStore({
317320
reducer,
318-
middleware: [],
319-
enhancers: [dummyEnhancer],
321+
middleware: new MiddlewareArray(),
322+
enhancers: new EnhancerArray(dummyEnhancer),
320323
})
321324

322325
expect(dummyEnhancerCalled).toBe(true)

packages/toolkit/src/tests/configureStore.typetest.ts

Lines changed: 43 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@ import type {
1010
} from 'redux'
1111
import { applyMiddleware, combineReducers } from 'redux'
1212
import type { PayloadAction, ConfigureStoreOptions } from '@reduxjs/toolkit'
13-
import { configureStore, createSlice } from '@reduxjs/toolkit'
13+
import {
14+
configureStore,
15+
createSlice,
16+
MiddlewareArray,
17+
EnhancerArray,
18+
} from '@reduxjs/toolkit'
1419
import type { ThunkMiddleware, ThunkAction, ThunkDispatch } from 'redux-thunk'
1520
import { thunk } from 'redux-thunk'
1621
import { expectNotAny, expectType } from './helpers'
@@ -67,20 +72,26 @@ const _anyMiddleware: any = () => () => () => {}
6772
}
6873

6974
/*
70-
* Test: configureStore() accepts middleware array.
75+
* Test: configureStore() accepts MiddlewareArray, but not plain array.
7176
*/
7277
{
7378
const middleware: Middleware = (store) => (next) => next
7479

7580
configureStore({
7681
reducer: () => 0,
82+
middleware: new MiddlewareArray(middleware),
83+
})
84+
85+
configureStore({
86+
reducer: () => 0,
87+
// @ts-expect-error
7788
middleware: [middleware],
7889
})
7990

8091
configureStore({
8192
reducer: () => 0,
8293
// @ts-expect-error
83-
middleware: ['not middleware'],
94+
middleware: new MiddlewareArray('not middleware'),
8495
})
8596
}
8697

@@ -133,13 +144,21 @@ const _anyMiddleware: any = () => () => () => {}
133144
}
134145

135146
/*
136-
* Test: configureStore() accepts store enhancer.
147+
* Test: configureStore() accepts store EnhancerArray, but not plain array
137148
*/
138149
{
139150
{
151+
const enhancer = applyMiddleware(() => (next) => next)
152+
140153
const store = configureStore({
141154
reducer: () => 0,
142-
enhancers: [applyMiddleware(() => (next) => next)] as const,
155+
enhancers: new EnhancerArray(enhancer),
156+
})
157+
158+
const store2 = configureStore({
159+
reducer: () => 0,
160+
// @ts-expect-error
161+
enhancers: [enhancer],
143162
})
144163

145164
expectType<Dispatch & ThunkDispatch<number, undefined, AnyAction>>(
@@ -150,7 +169,7 @@ const _anyMiddleware: any = () => () => () => {}
150169
configureStore({
151170
reducer: () => 0,
152171
// @ts-expect-error
153-
enhancers: ['not a store enhancer'],
172+
enhancers: new EnhancerArray('not a store enhancer'),
154173
})
155174

156175
{
@@ -178,10 +197,10 @@ const _anyMiddleware: any = () => () => () => {}
178197

179198
const store = configureStore({
180199
reducer: () => 0,
181-
enhancers: [
200+
enhancers: new EnhancerArray(
182201
somePropertyStoreEnhancer,
183-
anotherPropertyStoreEnhancer,
184-
] as const,
202+
anotherPropertyStoreEnhancer
203+
),
185204
})
186205

187206
expectType<Dispatch>(store.dispatch)
@@ -240,11 +259,10 @@ const _anyMiddleware: any = () => () => () => {}
240259

241260
const store = configureStore({
242261
reducer: () => ({ aProperty: 0 }),
243-
enhancers: [
262+
enhancers: new EnhancerArray(
244263
someStateExtendingEnhancer,
245-
anotherStateExtendingEnhancer,
246-
// this doesn't work without the as const
247-
] as const,
264+
anotherStateExtendingEnhancer
265+
),
248266
})
249267

250268
const state = store.getState()
@@ -512,7 +530,7 @@ const _anyMiddleware: any = () => () => () => {}
512530
{
513531
const store = configureStore({
514532
reducer: reducerA,
515-
middleware: [],
533+
middleware: new MiddlewareArray(),
516534
})
517535
// @ts-expect-error
518536
store.dispatch(thunkA())
@@ -525,7 +543,7 @@ const _anyMiddleware: any = () => () => () => {}
525543
{
526544
const store = configureStore({
527545
reducer: reducerA,
528-
middleware: [thunk] as [ThunkMiddleware<StateA>],
546+
middleware: new MiddlewareArray(thunk as ThunkMiddleware<StateA>),
529547
})
530548
store.dispatch(thunkA())
531549
// @ts-expect-error
@@ -537,21 +555,9 @@ const _anyMiddleware: any = () => () => () => {}
537555
{
538556
const store = configureStore({
539557
reducer: reducerA,
540-
middleware: [] as any as [Middleware<(a: StateA) => boolean, StateA>],
541-
})
542-
const result: boolean = store.dispatch(5)
543-
// @ts-expect-error
544-
const result2: string = store.dispatch(5)
545-
}
546-
/**
547-
* Test: read-only middleware tuple
548-
*/
549-
{
550-
const store = configureStore({
551-
reducer: reducerA,
552-
middleware: [] as any as readonly [
553-
Middleware<(a: StateA) => boolean, StateA>
554-
],
558+
middleware: new MiddlewareArray(
559+
0 as unknown as Middleware<(a: StateA) => boolean, StateA>
560+
),
555561
})
556562
const result: boolean = store.dispatch(5)
557563
// @ts-expect-error
@@ -561,11 +567,13 @@ const _anyMiddleware: any = () => () => () => {}
561567
* Test: multiple custom middleware
562568
*/
563569
{
564-
const middleware = [] as any as [
565-
Middleware<(a: 'a') => 'A', StateA>,
566-
Middleware<(b: 'b') => 'B', StateA>,
567-
ThunkMiddleware<StateA>
568-
]
570+
const middleware = [] as any as MiddlewareArray<
571+
[
572+
Middleware<(a: 'a') => 'A', StateA>,
573+
Middleware<(b: 'b') => 'B', StateA>,
574+
ThunkMiddleware<StateA>
575+
]
576+
>
569577
const store = configureStore({
570578
reducer: reducerA,
571579
middleware,

0 commit comments

Comments
 (0)