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