farmbot-web-frontend
Version:
Farmbot web frontend.
51 lines (39 loc) • 1.7 kB
text/typescript
import { ReduxAction } from "./interfaces";
import { defensiveClone } from "./util";
const NOOP = (s: any, a: ReduxAction<{}>) => s;
export function generateReducer<State>(
initialState: State,
/** Set "catch all" handler for unknown action names. Default is a no-op fn.
* Useful for logging / debugging. */
DEFAULT = NOOP) {
/** A function that responds to a particular action from within a generated reducer. */
interface ActionHandler {
(state: State, action: ReduxAction<any>): State;
}
interface GenericActionHandler<T> {
(state: State, action: ReduxAction<T>): State;
}
interface ActionHandlerDict {
[actionHandler: string]: ActionHandler;
DEFAULT: ActionHandler;
}
interface GeneratedReducer extends ActionHandler {
/** Adds action handler for current reducer. */
add: <T>(name: string,
fn: GenericActionHandler<T>) => GeneratedReducer; // Calms the type checker.
}
let actionHandlers: ActionHandlerDict = { DEFAULT };
let reducer: GeneratedReducer = function<T>(state = initialState,
action: ReduxAction<T>): State {
let handler = (actionHandlers[action.type] || actionHandlers["DEFAULT"]);
let clonedState = defensiveClone<State>(state);
let clonedAction = defensiveClone<ReduxAction<T>>(action);
let result: State = handler(clonedState, clonedAction);
return result;
} as GeneratedReducer;
reducer.add = function addHandler<T>(name: string, fn: GenericActionHandler<T>) {
actionHandlers[name] = fn;
return reducer;
};
return reducer;
}