import { combineReducers as redux_combineReducers } from 'redux' ; import { Action , Dispatch } from '../types/redux' ; import { Arg1 , Arg2 , If , Equals , IfArity2 , NonPartial } from '../types/helpers' ; import { ActionsFromHandlerMap , StateFromHandlerMap } from '../handler-map' ; import { INITIAL_STATE_KEY } from '../constants' ; import { HandlerMapConstraint } from '../handler-map' ; export type Reducer < S , A > = ( state : S | undefined , action : A ) => S ; export const createReducer = < HM extends HandlerMapConstraint < any > > ( handlerMap ) : Reducer < StateFromHandlerMap < HM > , ActionsFromHandlerMap < HM > > => { const initialState = ( handlerMap as any ) [ INITIAL_STATE_KEY ] ; return ( s , action ) : StateFromHandlerMap < HM > => { const handler = handlerMap [ action . type ] ; const oldS = s === undefined ? initialState : s ; let newS = handler ; if ( typeof handler === 'function' ) { newS = ( handler as any ) ( s , ( action as any ) . payload ) ; } if ( typeof newS === 'number' || typeof newS === 'string' || typeof newS === 'boolean' || typeof newS === 'symbol' || Array . isArray ( newS ) ) { return ( newS as any ) as StateFromHandlerMap < HM > ; } else if ( typeof newS === 'object' ) { return { ... ( oldS as any ) , ... ( newS as any ) } ; } else { return oldS ; } } ; } ; export type ReducersMapObject < S = any > = { [ K in keyof S ] : Reducer < S [ K ] , Action > ; } ; template S param reducers returns interface CombineReducers { < RM extends ReducersMapObject > ( reducers ) : Reducer < { [ K in keyof RM ] : StateFromReducer < RM [ K ] > ; } , { [ K in keyof RM ] : Arg2 < RM [ K ] > ; } [ keyof RM ] > ; } export const combineReducers = redux_combineReducers ; export type StateFromReducer < R extends Reducer < any , any > > = R extends Reducer < infer S , any > ? S : never ; export type ActionsFromReducer < R extends Reducer < any , any > > = R extends Reducer < any , infer A > ? A : never ; /**
 * Type of dispatch function that a store created with this
 * reducer would have.
 */ export type DispatchFromReducer < R extends Reducer < any , any > > = Dispatch < ActionsFromReducer < R > > ;