reducerFactory.ts 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. import { ActionOf, ActionCreator } from './actionCreatorFactory';
  2. import { Reducer } from 'redux';
  3. export interface HandlerConfig<State, Payload> {
  4. filter: ActionCreator<Payload>;
  5. handler: (state: State, action: ActionOf<Payload>) => State;
  6. }
  7. export interface AddHandler<State> {
  8. addHandler: <Payload>(config: HandlerConfig<State, Payload>) => CreateReducer<State>;
  9. }
  10. export interface CreateReducer<State> extends AddHandler<State> {
  11. create: () => Reducer<State, ActionOf<any>>;
  12. }
  13. export const reducerFactory = <State>(initialState: State): AddHandler<State> => {
  14. const allHandlerConfigs: Array<HandlerConfig<State, any>> = [];
  15. const addHandler = <Payload>(config: HandlerConfig<State, Payload>): CreateReducer<State> => {
  16. if (allHandlerConfigs.some(c => c.filter.type === config.filter.type)) {
  17. throw new Error(`There is already a handlers defined with the type ${config.filter.type}`);
  18. }
  19. allHandlerConfigs.push(config);
  20. return instance;
  21. };
  22. const create = (): Reducer<State, ActionOf<any>> => {
  23. const reducer: Reducer<State, ActionOf<any>> = (state: State = initialState, action: ActionOf<any>) => {
  24. const validHandlers = allHandlerConfigs
  25. .filter(config => config.filter.type === action.type)
  26. .map(config => config.handler);
  27. return validHandlers.reduce((currentState, handler) => {
  28. return handler(currentState, action);
  29. }, state || initialState);
  30. };
  31. return reducer;
  32. };
  33. const instance: CreateReducer<State> = {
  34. addHandler,
  35. create,
  36. };
  37. return instance;
  38. };