import { Middleware , MiddlewareAPI , applyMiddleware , createStore , Dispatch , Reducer , Action , AnyAction } from '../..' ; /**
 * Logger middleware doesn't add any extra types to dispatch, just logs actions
 * and state.
 */ function logger ( ) { const loggerMiddleware = ( { getState } ) => ( next ) => action => { console . log ( 'will dispatch' , action ) ; const returnValue = next ( action ) ; console . log ( 'state after dispatch' , getState ( ) ) ; return returnValue ; } ; return loggerMiddleware ; } /**
 * Promise middleware adds support for dispatching promises.
 */ type PromiseDispatch = < T extends Action > ( promise : Promise < T > ) => Promise < T > ; function promise ( ) { const promiseMiddleware = ( { dispatch } ) => next => < T extends Action > ( action ) => { if ( action instanceof Promise ) { action . then ( dispatch ) ; return action ; } return next ( action ) ; } ; return promiseMiddleware ; } /**
 * Thunk middleware adds support for dispatching thunks.
 */ interface Thunk < R , S , DispatchExt = { } > { ( dispatch , getState ) : R ; } interface ThunkDispatch < S , DispatchExt = { } > { < R > ( thunk ) : R ; } function thunk < S , DispatchExt > ( ) { const thunkMiddleware = api => ( next ) => < R > ( action ) => typeof action === 'function' ? action ( api . dispatch , api . getState ) : next ( action ) ; return thunkMiddleware ; } /**
 * Middleware that expects exact state type.
 */ function customState ( ) { type State = { field : 'string' ; } ; const customMiddleware = api => ( next ) => action => { api . getState ( ) . field ; api . getState ( ) . wrongField ; return next ( action ) ; } ; return customMiddleware ; } /**
 * Middleware that expects custom dispatch.
 */ function customDispatch ( ) { type MyAction = { type : 'INCREMENT' ; } | { type : 'DECREMENT' ; } ; type MyDispatch = Dispatch < MyAction > ; const customDispatch = ( api ) => next => action => { api . dispatch ( { type : 'INCREMENT' } ) ; api . dispatch ( { type : 'DECREMENT' } ) ; api . dispatch ( { type : 'UNKNOWN' } ) ; } ; } /**
 * Test the type of store.dispatch after applying different middleware.
 */ function apply ( ) { interface State { someField : 'string' ; } const reducer = null as any ; /**
     * logger
     */ const storeWithLogger = createStore ( reducer , applyMiddleware ( logger ( ) ) ) ; storeWithLogger . dispatch ( { type : 'INCREMENT' } ) ; storeWithLogger . dispatch ( Promise . resolve ( { type : 'INCREMENT' } ) ) ; storeWithLogger . dispatch ( 'not-an-action' ) ; /**
     * promise
     */ const storeWithPromise = createStore ( reducer , applyMiddleware ( promise ( ) ) ) ; storeWithPromise . dispatch ( { type : 'INCREMENT' } ) ; storeWithPromise . dispatch ( Promise . resolve ( { type : 'INCREMENT' } ) ) ; storeWithPromise . dispatch ( 'not-an-action' ) ; storeWithPromise . dispatch ( Promise . resolve ( 'not-an-action' ) ) ; /**
     * promise + logger
     */ const storeWithPromiseAndLogger = createStore ( reducer , applyMiddleware ( promise ( ) , logger ( ) ) ) ; storeWithPromiseAndLogger . dispatch ( { type : 'INCREMENT' } ) ; storeWithPromiseAndLogger . dispatch ( Promise . resolve ( { type : 'INCREMENT' } ) ) ; storeWithPromiseAndLogger . dispatch ( 'not-an-action' ) ; storeWithPromiseAndLogger . dispatch ( Promise . resolve ( 'not-an-action' ) ) ; /**
     * promise + thunk
     */ const storeWithPromiseAndThunk = createStore ( reducer , applyMiddleware ( promise ( ) , thunk < State , PromiseDispatch > ( ) , logger ( ) ) ) ; storeWithPromiseAndThunk . dispatch ( { type : 'INCREMENT' } ) ; storeWithPromiseAndThunk . dispatch ( Promise . resolve ( { type : 'INCREMENT' } ) ) ; storeWithPromiseAndThunk . dispatch ( ( dispatch , getState ) => { getState ( ) . someField ; getState ( ) . wrongField ; dispatch ( { type : 'INCREMENT' } ) ; dispatch ( dispatch => dispatch ( { type : 'INCREMENT' } ) ) ; dispatch ( Promise . resolve ( { type : 'INCREMENT' } ) ) ; dispatch ( 'not-an-action' ) ; } ) ; storeWithPromiseAndThunk . dispatch ( 'not-an-action' ) ; storeWithPromiseAndThunk . dispatch ( Promise . resolve ( 'not-an-action' ) ) ; /**
     * Test variadic signature.
     */ const storeWithLotsOfMiddleware = createStore ( reducer , applyMiddleware < PromiseDispatch > ( promise ( ) , logger ( ) , logger ( ) , logger ( ) , logger ( ) , logger ( ) ) ) ; storeWithLotsOfMiddleware . dispatch ( { type : 'INCREMENT' } ) ; storeWithLotsOfMiddleware . dispatch ( Promise . resolve ( { type : 'INCREMENT' } ) ) ; }