diff --git a/src/index.ts b/src/index.ts index c57e7b4..5a08ecc 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,122 +1,112 @@ import { Action, ActionCreator, AnyAction } from "typescript-fsa"; -export interface ReducerBuilder { +export interface ReducerBuilder { case

( actionCreator: ActionCreator

, handler: Handler, - ): ReducerBuilder; + ): ReducerBuilder; caseWithAction

( actionCreator: ActionCreator

, handler: Handler>, - ): ReducerBuilder; + ): ReducerBuilder; // cases variadic overloads - cases( - actionCreators: [ActionCreator], - handler: Handler, - ): ReducerBuilder; cases( actionCreators: [ActionCreator, ActionCreator], handler: Handler, - ): ReducerBuilder; + ): ReducerBuilder; cases( actionCreators: [ ActionCreator, ActionCreator, - ActionCreator + ActionCreator, ], handler: Handler, - ): ReducerBuilder; + ): ReducerBuilder; cases( actionCreators: [ ActionCreator, ActionCreator, ActionCreator, - ActionCreator + ActionCreator, ], handler: Handler, - ): ReducerBuilder; + ): ReducerBuilder; cases

( actionCreators: Array>, handler: Handler, - ): ReducerBuilder; + ): ReducerBuilder; // casesWithAction variadic overloads - casesWithAction( - actionCreators: [ActionCreator], - handler: Handler>, - ): ReducerBuilder; casesWithAction( actionCreators: [ActionCreator, ActionCreator], handler: Handler>, - ): ReducerBuilder; + ): ReducerBuilder; casesWithAction( actionCreators: [ ActionCreator, ActionCreator, - ActionCreator + ActionCreator, ], handler: Handler>, - ): ReducerBuilder; + ): ReducerBuilder; casesWithAction( actionCreators: [ ActionCreator, ActionCreator, ActionCreator, - ActionCreator + ActionCreator, ], handler: Handler>, - ): ReducerBuilder; + ): ReducerBuilder; casesWithAction

( actionCreators: Array>, handler: Handler>, - ): ReducerBuilder; + ): ReducerBuilder; withHandling( updateBuilder: ( - builder: ReducerBuilder, - ) => ReducerBuilder, - ): ReducerBuilder; + builder: ReducerBuilder, + ) => ReducerBuilder, + ): ReducerBuilder; // Intentionally avoid AnyAction in return type so packages can export reducers // created using .default() or .build() without requiring a dependency on typescript-fsa. default( defaultHandler: Handler, - ): (state: InS | undefined, action: { type: any }) => OutS; - build(): (state: InS | undefined, action: { type: any }) => OutS; - (state: InS | undefined, action: AnyAction): OutS; + ): (state: PassedS, action: AnyAction) => OutS; + build(): (state: PassedS, action: AnyAction) => OutS; + (state: PassedS, action: AnyAction): OutS; } -export type Handler = ( - state: InS, - payload: P, -) => OutS; +export type Handler = (state: InS, payload: P) => OutS; export function reducerWithInitialState(initialState: S): ReducerBuilder { - return makeReducer(initialState); + return makeReducer(initialState); } -export function reducerWithoutInitialState(): ReducerBuilder { - return makeReducer(); +export function reducerWithoutInitialState(): ReducerBuilder { + return makeReducer(); } export function upcastingReducer(): ReducerBuilder< InS, - OutS + OutS, + InS > { - return makeReducer(); + return makeReducer(); } -function makeReducer( +function makeReducer( initialState?: InS, -): ReducerBuilder { +): ReducerBuilder { const handlersByActionType: { [actionType: string]: Handler; } = {}; const reducer = getReducerFunction( initialState, handlersByActionType, - ) as ReducerBuilder; + ) as ReducerBuilder; reducer.caseWithAction =

( actionCreator: ActionCreator

, @@ -154,12 +144,12 @@ function makeReducer( reducer.withHandling = ( updateBuilder: ( - builder: ReducerBuilder, - ) => ReducerBuilder, + builder: ReducerBuilder, + ) => ReducerBuilder, ) => updateBuilder(reducer); reducer.default = (defaultHandler: Handler) => - getReducerFunction( + getReducerFunction( initialState, { ...handlersByActionType }, defaultHandler, @@ -171,13 +161,16 @@ function makeReducer( return reducer; } -function getReducerFunction( +function getReducerFunction( initialState: InS | undefined, handlersByActionType: { [actionType: string]: Handler }, defaultHandler?: Handler, ) { - return (state = initialState as InS, action: AnyAction) => { + return (passedState: PassedS, action: AnyAction) => { + const state = passedState !== undefined ? passedState : initialState; const handler = handlersByActionType[action.type] || defaultHandler; - return handler ? handler(state, action) : state; + return handler + ? handler(state as InS, action) + : ((state as unknown) as OutS); }; }