Skip to content

Commit a390f47

Browse files
committed
Merge branch 'special-array' into enhancer-callback-2
2 parents ed00f97 + 4e119df commit a390f47

20 files changed

+225
-182
lines changed

docs/api/actionCreatorMiddleware.mdx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export default function (state = {}, action: any) {
4747
import {
4848
configureStore,
4949
createActionCreatorInvariantMiddleware,
50+
Tuple,
5051
} from '@reduxjs/toolkit'
5152
import reducer from './reducer'
5253

@@ -62,6 +63,6 @@ const actionCreatorMiddleware = createActionCreatorInvariantMiddleware({
6263

6364
const store = configureStore({
6465
reducer,
65-
middleware: [actionCreatorMiddleware],
66+
middleware: new Tuple(actionCreatorMiddleware),
6667
})
6768
```

docs/api/configureStore.mdx

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,22 @@ and should return a middleware array.
9494
For more details on how the `middleware` parameter works and the list of middleware that are added by default, see the
9595
[`getDefaultMiddleware` docs page](./getDefaultMiddleware.mdx).
9696

97+
:::note Tuple
98+
Typescript users are required to use a `Tuple` instance (if not using a `getDefaultMiddleware` result, which is already a `Tuple`), for better inference.
99+
100+
```ts no-transpile
101+
import { configureStore, Tuple } from '@reduxjs/toolkit'
102+
103+
configureStore({
104+
reducer: rootReducer,
105+
middleware: new Tuple(additionalMiddleware, logger),
106+
})
107+
```
108+
109+
Javascript-only users are free to use a plain array if preferred.
110+
111+
:::
112+
97113
### `devTools`
98114
99115
If this is a boolean, it will be used to indicate whether `configureStore` should automatically enable support for [the Redux DevTools browser extension](https://github.com/reduxjs/redux-devtools).
@@ -122,7 +138,7 @@ If defined as an array, these will be passed to [the Redux `compose` function](h
122138
123139
This should _not_ include `applyMiddleware()` or the Redux DevTools Extension `composeWithDevTools`, as those are already handled by `configureStore`.
124140
125-
Example: `enhancers: [offline]` will result in a final setup of `[applyMiddleware, offline, devToolsExtension]`.
141+
Example: `enhancers: new Tuple(offline)` will result in a final setup of `[applyMiddleware, offline, devToolsExtension]`.
126142
127143
If defined as a callback function, it will be called with the existing array of enhancers _without_ the DevTools Extension (currently `[applyMiddleware]`),
128144
and should return a new array of enhancers. This is primarily useful for cases where a store enhancer needs to be added
@@ -131,6 +147,22 @@ in front of `applyMiddleware`, such as `redux-first-router` or `redux-offline`.
131147
Example: `enhancers: (defaultEnhancers) => defaultEnhancers.prepend(offline)` will result in a final setup
132148
of `[offline, applyMiddleware, devToolsExtension]`.
133149
150+
:::note Tuple
151+
Typescript users are required to use a `Tuple` instance (if not using a `getDefaultEnhancer` result, which is already a `Tuple`), for better inference.
152+
153+
```ts no-transpile
154+
import { configureStore, Tuple } from '@reduxjs/toolkit'
155+
156+
configureStore({
157+
reducer: rootReducer,
158+
enhancers: new Tuple(offline),
159+
})
160+
```
161+
162+
Javascript-only users are free to use a plain array if preferred.
163+
164+
:::
165+
134166
## Usage
135167
136168
### Basic Example

docs/api/getDefaultMiddleware.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ If you want to customize the list of middleware, you can supply an array of midd
2828
```js
2929
const store = configureStore({
3030
reducer: rootReducer,
31-
middleware: [thunk, logger],
31+
middleware: new Tuple(thunk, logger),
3232
})
3333

3434
// Store specifically has the thunk and logger middleware applied
@@ -55,7 +55,7 @@ const store = configureStore({
5555
// Store has all of the default middleware added, _plus_ the logger middleware
5656
```
5757

58-
It is preferable to use the chainable `.concat(...)` and `.prepend(...)` methods of the returned `MiddlewareArray` instead of the array spread operator, as the latter can lose valuable type information under some circumstances.
58+
It is preferable to use the chainable `.concat(...)` and `.prepend(...)` methods of the returned `Tuple` instead of the array spread operator, as the latter can lose valuable type information under some circumstances.
5959

6060
## Included Default Middleware
6161

docs/api/immutabilityMiddleware.mdx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ export default exampleSlice.reducer
7474
import {
7575
configureStore,
7676
createImmutableStateInvariantMiddleware,
77+
Tuple,
7778
} from '@reduxjs/toolkit'
7879

7980
import exampleSliceReducer from './exampleSlice'
@@ -85,7 +86,7 @@ const immutableInvariantMiddleware = createImmutableStateInvariantMiddleware({
8586
const store = configureStore({
8687
reducer: exampleSliceReducer,
8788
// Note that this will replace all default middleware
88-
middleware: [immutableInvariantMiddleware],
89+
middleware: new Tuple(immutableInvariantMiddleware),
8990
})
9091
```
9192

docs/api/serializabilityMiddleware.mdx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ import {
9393
configureStore,
9494
createSerializableStateInvariantMiddleware,
9595
isPlain,
96+
Tuple,
9697
} from '@reduxjs/toolkit'
9798
import reducer from './reducer'
9899

@@ -110,7 +111,7 @@ const serializableMiddleware = createSerializableStateInvariantMiddleware({
110111

111112
const store = configureStore({
112113
reducer,
113-
middleware: [serializableMiddleware],
114+
middleware: new Tuple(serializableMiddleware),
114115
})
115116
```
116117

docs/usage/usage-with-typescript.md

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ export default store
9999

100100
The type of the `dispatch` function type will be directly inferred from the `middleware` option. So if you add _correctly typed_ middlewares, `dispatch` should already be correctly typed.
101101

102-
As TypeScript often widens array types when combining arrays using the spread operator, we suggest using the `.concat(...)` and `.prepend(...)` methods of the `MiddlewareArray` returned by `getDefaultMiddleware()`.
102+
As TypeScript often widens array types when combining arrays using the spread operator, we suggest using the `.concat(...)` and `.prepend(...)` methods of the `Tuple` returned by `getDefaultMiddleware()`.
103103

104104
```ts
105105
import { configureStore } from '@reduxjs/toolkit'
@@ -134,25 +134,18 @@ export type AppDispatch = typeof store.dispatch
134134
export default store
135135
```
136136

137-
#### Using `MiddlewareArray` without `getDefaultMiddleware`
137+
#### Using `Tuple` without `getDefaultMiddleware`
138138

139-
If you want to skip the usage of `getDefaultMiddleware` altogether, you can still use `MiddlewareArray` for type-safe concatenation of your `middleware` array. This class extends the default JavaScript `Array` type, only with modified typings for `.concat(...)` and the additional `.prepend(...)` method.
139+
If you want to skip the usage of `getDefaultMiddleware` altogether, you are requred to use `Tuple` for type-safe creation of your `middleware` array. This class extends the default JavaScript `Array` type, only with modified typings for `.concat(...)` and the additional `.prepend(...)` method.
140140

141-
This is generally not required though, as you will probably not run into any array-type-widening issues as long as you are using `as const` and do not use the spread operator.
142-
143-
So the following two calls would be equivalent:
141+
For example:
144142

145143
```ts
146-
import { configureStore, MiddlewareArray } from '@reduxjs/toolkit'
147-
148-
configureStore({
149-
reducer: rootReducer,
150-
middleware: new MiddlewareArray().concat(additionalMiddleware, logger),
151-
})
144+
import { configureStore, Tuple } from '@reduxjs/toolkit'
152145

153146
configureStore({
154147
reducer: rootReducer,
155-
middleware: [additionalMiddleware, logger] as const,
148+
middleware: new Tuple(additionalMiddleware, logger),
156149
})
157150
```
158151

packages/toolkit/src/configureStore.ts

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import type {
2323
ExtractStoreExtensions,
2424
ExtractStateExtensions,
2525
} from './tsHelpers'
26-
import type { MiddlewareArray, EnhancerArray } from './utils'
26+
import type { Tuple } from './utils'
2727
import type { GetDefaultEnhancers } from './getDefaultEnhancers'
2828
import { buildGetDefaultEnhancers } from './getDefaultEnhancers'
2929

@@ -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 MiddlewareArray<Middlewares<S>> = MiddlewareArray<Middlewares<S>>,
41-
E extends EnhancerArray<Enhancers> = EnhancerArray<Enhancers>,
40+
M extends Tuple<Middlewares<S>> = Tuple<Middlewares<S>>,
41+
E extends Tuple<Enhancers> = Tuple<Enhancers>,
4242
P = S
4343
> {
4444
/**
@@ -48,8 +48,8 @@ export interface ConfigureStoreOptions<
4848
reducer: Reducer<S, A, P> | ReducersMapObject<S, A, P>
4949

5050
/**
51-
* An array of Redux middleware to install. If not supplied, defaults to
52-
* the set of middleware returned by `getDefaultMiddleware()`.
51+
* An array of Redux middleware to install, or a callback receiving `getDefaultMiddleware` and returning a Tuple of middleware.
52+
* If not supplied, defaults to the set of middleware returned by `getDefaultMiddleware()`.
5353
*
5454
* @example `middleware: (gDM) => gDM().concat(logger, apiMiddleware, yourCustomMiddleware)`
5555
* @see https://redux-toolkit.js.org/api/getDefaultMiddleware#intended-usage
@@ -78,8 +78,8 @@ export interface ConfigureStoreOptions<
7878
* The store enhancers to apply. See Redux's `createStore()`.
7979
* All enhancers will be included before the DevTools Extension enhancer.
8080
* If you need to customize the order of enhancers, supply a callback
81-
* function that will receive a `getDefaultEnhancers` function that returns an EnhancerArray,
82-
* and should return a new array (such as `getDefaultEnhancers().concat(offline)`).
81+
* function that will receive a `getDefaultEnhancers` function that returns a Tuple,
82+
* and should return a Tuple of enhancers (such as `getDefaultEnhancers().concat(offline)`).
8383
* If you only need to add middleware, you can use the `middleware` parameter instead.
8484
*/
8585
enhancers?: (getDefaultEnhancers: GetDefaultEnhancers<M>) => E
@@ -112,10 +112,8 @@ export type EnhancedStore<
112112
export function configureStore<
113113
S = any,
114114
A extends Action = AnyAction,
115-
M extends MiddlewareArray<Middlewares<S>> = MiddlewareArray<
116-
[ThunkMiddlewareFor<S>]
117-
>,
118-
E extends EnhancerArray<Enhancers> = EnhancerArray<
115+
M extends Tuple<Middlewares<S>> = Tuple<[ThunkMiddlewareFor<S>]>,
116+
E extends Tuple<Enhancers> = Tuple<
119117
[StoreEnhancer<{ dispatch: ExtractDispatchExtensions<M> }>, StoreEnhancer]
120118
>,
121119
P = S

packages/toolkit/src/getDefaultEnhancers.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { StoreEnhancer } from 'redux'
22
import type { AutoBatchOptions } from './autoBatchEnhancer'
33
import { autoBatchEnhancer } from './autoBatchEnhancer'
4-
import { EnhancerArray } from './utils'
4+
import { Tuple } from './utils'
55
import type { Middlewares } from './configureStore'
66
import type { ExtractDispatchExtensions } from './tsHelpers'
77

@@ -11,15 +11,15 @@ type GetDefaultEnhancersOptions = {
1111

1212
export type GetDefaultEnhancers<M extends Middlewares<any>> = (
1313
options?: GetDefaultEnhancersOptions
14-
) => EnhancerArray<[StoreEnhancer<{ dispatch: ExtractDispatchExtensions<M> }>]>
14+
) => Tuple<[StoreEnhancer<{ dispatch: ExtractDispatchExtensions<M> }>]>
1515

1616
export const buildGetDefaultEnhancers = <M extends Middlewares<any>>(
1717
middlewareEnhancer: StoreEnhancer<{ dispatch: ExtractDispatchExtensions<M> }>
1818
): GetDefaultEnhancers<M> =>
1919
function getDefaultEnhancers(options) {
2020
const { autoBatch = true } = options ?? {}
2121

22-
let enhancerArray = new EnhancerArray<StoreEnhancer[]>(middlewareEnhancer)
22+
let enhancerArray = new Tuple<StoreEnhancer[]>(middlewareEnhancer)
2323
if (autoBatch) {
2424
enhancerArray.push(
2525
autoBatchEnhancer(typeof autoBatch === 'object' ? autoBatch : undefined)

packages/toolkit/src/getDefaultMiddleware.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { createImmutableStateInvariantMiddleware } from './immutableStateInvaria
1111
import type { SerializableStateInvariantMiddlewareOptions } from './serializableStateInvariantMiddleware'
1212
import { createSerializableStateInvariantMiddleware } from './serializableStateInvariantMiddleware'
1313
import type { ExcludeFromTuple } from './tsHelpers'
14-
import { MiddlewareArray } from './utils'
14+
import { Tuple } from './utils'
1515

1616
function isBoolean(x: any): x is boolean {
1717
return typeof x === 'boolean'
@@ -48,7 +48,7 @@ export type GetDefaultMiddleware<S = any> = <
4848
}
4949
>(
5050
options?: O
51-
) => MiddlewareArray<ExcludeFromTuple<[ThunkMiddlewareFor<S, O>], never>>
51+
) => Tuple<ExcludeFromTuple<[ThunkMiddlewareFor<S, O>], never>>
5252

5353
export const buildGetDefaultMiddleware = <S = any>(): GetDefaultMiddleware<S> =>
5454
function getDefaultMiddleware(options) {
@@ -59,7 +59,7 @@ export const buildGetDefaultMiddleware = <S = any>(): GetDefaultMiddleware<S> =>
5959
actionCreatorCheck = true,
6060
} = options ?? {}
6161

62-
let middlewareArray = new MiddlewareArray<Middleware[]>()
62+
let middlewareArray = new Tuple<Middleware[]>()
6363

6464
if (thunk) {
6565
if (isBoolean(thunk)) {

packages/toolkit/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ export type {
101101
// types
102102
ActionReducerMapBuilder,
103103
} from './mapBuilders'
104-
export { MiddlewareArray, EnhancerArray } from './utils'
104+
export { Tuple } from './utils'
105105

106106
export { createEntityAdapter } from './entities/create_adapter'
107107
export type {

0 commit comments

Comments
 (0)