import { Reducer , AnyAction } from 'redux' ; import { ActionType , getType } from 'typesafe-actions' ; import { ActionCreator , StringOrSymbol } from 'typesafe-actions/dist/types' ; type ActionMap = { [ key ] : ActionType < any > ; } ; type Handlers < S , T extends ActionMap > = { [ K in keyof T ] ? : T [ K ] extends ActionCreator < StringOrSymbol > ? ( prevState : S , payload : ReturnType < T [ K ] > [ 'payload' ] , meta : ReturnType < T [ K ] > [ 'meta' ] ) => S : T [ K ] extends object ? Handlers < S , T [ K ] > : never ; } ; export function createReducer < S , T extends ActionMap > ( initialState , actions ) { return handlers => { const actionTypes = { } ; const processHandlers = ( handlerGroup ) => { Object . keys ( actions ) . forEach ( key => { if ( typeof handlerGroup [ key ] === 'object' ) { return Object . assign ( actionTypes , processHandlers ( handlerGroup [ key ] ) ) ; } if ( ! handlerGroup [ key ] ) return ; actionTypes [ getType ( actions [ key ] ) ] = handlerGroup [ key ] ; } ) ; } ; processHandlers ( handlers ) ; return ( state = initialState , action ) => { if ( actionTypes [ action . type ] ) { return actionTypes [ action . type ] ( state , action . payload , action . meta ) ; } return state ; } ; } ; }