1import compose from './compose'; 2import type { Middleware, MiddlewareAPI } from './types/middleware'; 3import type { AnyAction } from './types/actions'; 4import type { Dispatch, PreloadedState, StoreEnhancer, StoreEnhancerStoreCreator } from './types/store'; 5import type { Reducer } from './types/reducers'; 6 7/** 8 * Creates a store enhancer that applies middleware to the dispatch method 9 * of the Redux store. This is handy for a variety of tasks, such as expressing 10 * asynchronous actions in a concise manner, or logging every action payload. 11 * 12 * See `redux-thunk` package as an example of the Redux middleware. 13 * 14 * Because middleware is potentially asynchronous, this should be the first 15 * store enhancer in the composition chain. 16 * 17 * Note that each middleware will be given the `dispatch` and `getState` functions 18 * as named arguments. 19 * 20 * @param middlewares The middleware chain to be applied. 21 * @returns A store enhancer applying the middleware. 22 * 23 * @template Ext Dispatch signature added by a middleware. 24 * @template S The type of the state supported by a middleware. 25 */ 26export default function applyMiddleware(): StoreEnhancer 27export default function applyMiddleware<Ext1, S>( 28 middleware1: Middleware<Ext1, S, any> 29): StoreEnhancer<{ dispatch: Ext1 }> 30export default function applyMiddleware<Ext1, Ext2, S>( 31 middleware1: Middleware<Ext1, S, any>, 32 middleware2: Middleware<Ext2, S, any> 33): StoreEnhancer<{ dispatch: Ext1 & Ext2 }> 34export default function applyMiddleware<Ext1, Ext2, Ext3, S>( 35 middleware1: Middleware<Ext1, S, any>, 36 middleware2: Middleware<Ext2, S, any>, 37 middleware3: Middleware<Ext3, S, any> 38): StoreEnhancer<{ dispatch: Ext1 & Ext2 & Ext3 }> 39export default function applyMiddleware<Ext1, Ext2, Ext3, Ext4, S>( 40 middleware1: Middleware<Ext1, S, any>, 41 middleware2: Middleware<Ext2, S, any>, 42 middleware3: Middleware<Ext3, S, any>, 43 middleware4: Middleware<Ext4, S, any> 44): StoreEnhancer<{ dispatch: Ext1 & Ext2 & Ext3 & Ext4 }> 45export default function applyMiddleware<Ext1, Ext2, Ext3, Ext4, Ext5, S>( 46 middleware1: Middleware<Ext1, S, any>, 47 middleware2: Middleware<Ext2, S, any>, 48 middleware3: Middleware<Ext3, S, any>, 49 middleware4: Middleware<Ext4, S, any>, 50 middleware5: Middleware<Ext5, S, any> 51): StoreEnhancer<{ dispatch: Ext1 & Ext2 & Ext3 & Ext4 & Ext5 }> 52export default function applyMiddleware<Ext, S = any>( 53 ...middlewares: Middleware<any, S, any>[] 54): StoreEnhancer<{ dispatch: Ext }> 55export default function applyMiddleware( 56 ...middlewares: Middleware[] 57): StoreEnhancer<any> { 58 return (createStore: StoreEnhancerStoreCreator) => 59 <S, A extends AnyAction>( 60 reducer: Reducer<S, A>, 61 preloadedState?: PreloadedState<S> 62 ) => { 63 const store = createStore(reducer, preloadedState) 64 let dispatch: Dispatch = () => { 65 throw new Error( 66 'Dispatching while constructing your middleware is not allowed. ' + 67 'Other middleware would not be applied to this dispatch.' 68 ) 69 } 70 71 const middlewareAPI: MiddlewareAPI = { 72 getState: store.getState, 73 dispatch: (action, ...args) => dispatch(action, ...args) 74 } 75 const chain = middlewares.map(middleware => middleware(middlewareAPI)) 76 dispatch = compose<typeof dispatch>(...chain)(store.dispatch) 77 78 return { 79 ...store, 80 dispatch 81 } 82 } 83} 84