import type { Draft } from 'immer' ; import createNextState , { isDraft , isDraftable } from 'immer' ; import type { AnyAction , Action , Reducer } from 'redux' ; import type { ActionReducerMapBuilder } from './mapBuilders' ; import { executeReducerBuilderCallback } from './mapBuilders' ; import type { NoInfer } from './tsHelpers' ; deprecated public export type Actions < T extends keyof any = string > = Record < T , Action > ; export interface ActionMatcher < A extends AnyAction > { ( action ) : action is A ; } export type ActionMatcherDescription < S , A extends AnyAction > = { matcher : ActionMatcher < A > ; reducer : CaseReducer < S , NoInfer < A > > ; } ; export type ReadonlyActionMatcherDescriptionCollection < S > = ReadonlyArray < ActionMatcherDescription < S , any > > ; export type ActionMatcherDescriptionCollection < S > = Array < ActionMatcherDescription < S , any > > ; public export type CaseReducer < S = any , A extends Action = AnyAction > = ( state : Draft < S > , action : A ) => S | void | Draft < S > ; deprecated public export type CaseReducers < S , AS extends Actions > = { [ T in keyof AS ] : AS [ T ] extends Action ? CaseReducer < S , AS [ T ] > : void ; } ; export type NotFunction < T > = T extends Function ? never : T ; function isStateFunction < S > ( x ) { return typeof x === 'function' ; } export type ReducerWithInitialState < S extends NotFunction < any > > = Reducer < S > & { getInitialState : ( ) => S ; } ; remarks overloadSummary param initialState param builderCallback example public export function createReducer < S extends NotFunction < any > > ( initialState , builderCallback ) ; overloadSummary param initialState param actionsMap param actionMatchers param defaultCaseReducer example public export function createReducer < S extends NotFunction < any > , CR extends CaseReducers < S , any > = CaseReducers < S , any > > ( initialState , actionsMap , actionMatchers ? , defaultCaseReducer ? ) ; export function createReducer < S extends NotFunction < any > > ( initialState , mapOrBuilderCallback , actionMatchers = [ ] , defaultCaseReducer ? ) { let [ actionsMap , finalActionMatchers , finalDefaultCaseReducer ] = typeof mapOrBuilderCallback === 'function' ? executeReducerBuilderCallback ( mapOrBuilderCallback ) : [ mapOrBuilderCallback , actionMatchers , defaultCaseReducer ] ; let getInitialState ; if ( isStateFunction ( initialState ) ) { getInitialState = ( ) => createNextState ( initialState ( ) , ( ) => { } ) ; } else { const frozenInitialState = createNextState ( initialState , ( ) => { } ) ; getInitialState = ( ) => frozenInitialState ; } function reducer ( state = getInitialState ( ) , action ) { let caseReducers = [ actionsMap [ action . type ] , ... finalActionMatchers . filter ( ( { matcher } ) => matcher ( action ) ) . map ( ( { reducer } ) => reducer ) , ] ; if ( caseReducers . filter ( ( cr ) => ! ! cr ) . length === 0 ) { caseReducers = [ finalDefaultCaseReducer ] ; } return caseReducers . reduce ( ( previousState , caseReducer ) : S => { if ( caseReducer ) { if ( isDraft ( previousState ) ) { const draft = previousState as Draft < S > ; const result = caseReducer ( draft , action ) ; if ( typeof result === 'undefined' ) { return previousState ; } return result as S ; } else if ( ! isDraftable ( previousState ) ) { const result = caseReducer ( previousState as any , action ) ; if ( typeof result === 'undefined' ) { if ( previousState === null ) { return previousState ; } throw Error ( 'A case reducer on a non-draftable value must not return undefined' ) ; } return result as S ; } else { return createNextState ( previousState , ( draft ) => { return caseReducer ( draft , action ) ; } ) ; } } return previousState ; } , state ) ; } reducer . getInitialState = getInitialState ; return reducer as ReducerWithInitialState < S > ; }