import { StoreEnhancer , Action , AnyAction , Reducer , createStore } from '../..' ; interface State { someField : 'string' ; } const reducer = null as any ; /**
 * Store enhancer that extends the type of dispatch.
 */ function dispatchExtension ( ) { type PromiseDispatch = < T extends Action > ( promise : Promise < T > ) => Promise < T > ; const enhancer = createStore => < S , A extends Action = AnyAction > ( reducer , preloadedState ? ) => { const store = createStore ( reducer , preloadedState ) ; return { ... store , dispatch : ( action ) => { if ( action . type ) { store . dispatch ( action ) ; } else if ( action . then ) { action . then ( store . dispatch ) ; } return action ; } } ; } ; const store = createStore ( reducer , enhancer ) ; store . dispatch ( { type : 'INCREMENT' } ) ; store . dispatch ( Promise . resolve ( { type : 'INCREMENT' } ) ) ; store . dispatch ( 'not-an-action' ) ; store . dispatch ( Promise . resolve ( 'not-an-action' ) ) ; } /**
 * Store enhancer that extends the type of the state.
 */ function stateExtension ( ) { interface ExtraState { extraField : 'extra' ; } const enhancer = createStore => < S , A extends Action = AnyAction > ( reducer , preloadedState ? ) => { const wrappedReducer = ( state , action ) => { const newState = reducer ( state , action ) ; return { ... newState , extraField : 'extra' } ; } ; const wrappedPreloadedState = preloadedState ? { ... preloadedState , extraField : 'extra' } : undefined ; return createStore ( wrappedReducer , wrappedPreloadedState ) ; } ; const store = createStore ( reducer , enhancer ) ; store . getState ( ) . someField ; store . getState ( ) . extraField ; store . getState ( ) . wrongField ; } /**
 * Store enhancer that adds methods to the store.
 */ function extraMethods ( ) { const enhancer = createStore => ( ... args ) => { const store = createStore ( ... args ) ; store . method = ( ) => 'foo' ; return store ; } ; const store = createStore ( reducer , enhancer ) ; store . getState ( ) ; const res = store . method ( ) ; store . wrongMethod ( ) ; } /**
 * replaceReducer with a store enhancer
 */ function replaceReducerExtender ( ) { interface ExtraState { extraField : 'extra' ; } const enhancer = createStore => < S , A extends Action = AnyAction > ( reducer , preloadedState ? ) => { const wrappedReducer = ( state , action ) => { const newState = reducer ( state , action ) ; return { ... newState , extraField : 'extra' } ; } ; const wrappedPreloadedState = preloadedState ? { ... preloadedState , extraField : 'extra' } : undefined ; return createStore ( wrappedReducer , wrappedPreloadedState ) ; } ; const store = createStore ( reducer , enhancer ) ; const newReducer = ( state = { test : true } , _ ) => state ; const newStore = store . replaceReducer ( newReducer ) ; newStore . getState ( ) . test ; newStore . getState ( ) . extraField ; newStore . getState ( ) . wrongField ; const res = newStore . method ( ) ; newStore . wrongMethod ( ) ; } function mhelmersonExample ( ) { interface State { someField : 'string' ; } interface ExtraState { extraField : 'extra' ; } const reducer = null as any ; function stateExtensionExpectedToWork ( ) { interface ExtraState { extraField : 'extra' ; } const enhancer = createStore => < S , A extends Action = AnyAction > ( reducer , preloadedState ? ) => { const wrappedReducer = ( state , action ) => { const newState = reducer ( state , action ) ; return { ... newState , extraField : 'extra' } ; } ; const wrappedPreloadedState = preloadedState ? { ... preloadedState , extraField : 'extra' } : undefined ; const store = createStore ( wrappedReducer , wrappedPreloadedState ) ; return { ... store , replaceReducer < NS , NA extends Action = AnyAction > ( nextReducer ) { const nextWrappedReducer = ( state , action ) => { const newState = nextReducer ( state , action ) ; return { ... newState , extraField : 'extra' } ; } ; return store . replaceReducer ( nextWrappedReducer ) ; } } ; } ; const store = createStore ( reducer , enhancer ) ; store . replaceReducer ( reducer ) ; store . getState ( ) . extraField ; store . getState ( ) . wrongField ; store . getState ( ) . test ; const newReducer = ( state = { test : true } , _ ) => state ; const newStore = store . replaceReducer ( newReducer ) ; newStore . getState ( ) . test ; newStore . getState ( ) . extraField ; newStore . getState ( ) . wrongField ; } } function finalHelmersonExample ( ) { interface ExtraState { foo : string ; } function persistReducer < S , A extends AnyAction > ( config , reducer ) { return ( state , action ) => { const newState = reducer ( state , action as unknown as A ) ; return { ... newState , foo : 'hi' } ; } ; } function persistStore < S > ( store ) { return store ; } function createPersistEnhancer ( persistConfig ) { return createStore => < S , A extends Action = AnyAction > ( reducer , preloadedState ? ) => { const persistedReducer = persistReducer < S , A > ( persistConfig , reducer ) ; const store = createStore ( persistedReducer , preloadedState ) ; const persistor = persistStore ( store ) ; return { ... store , replaceReducer : nextReducer => { return store . replaceReducer ( persistReducer ( persistConfig , nextReducer ) ) ; } , persistor } ; } ; } const store = createStore ( reducer , createPersistEnhancer ( 'hi' ) ) ; store . getState ( ) . foo ; store . getState ( ) . wrongField ; const newReducer = ( state = { test : true } , _ ) => state ; const newStore = store . replaceReducer ( newReducer ) ; newStore . getState ( ) . test ; newStore . getState ( ) . whatever ; newStore . getState ( ) . wrongField ; }