reducerFactory.ts 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. import { ActionOf, ActionCreator } from './actionCreatorFactory';
  2. import { Reducer } from 'redux';
  3. export type Mapper<State, Payload> = (state: State, action: ActionOf<Payload>) => State;
  4. export interface MapperConfig<State, Payload> {
  5. filter: ActionCreator<Payload>;
  6. mapper: Mapper<State, Payload>;
  7. }
  8. export interface AddMapper<State> {
  9. addMapper: <Payload>(config: MapperConfig<State, Payload>) => CreateReducer<State>;
  10. }
  11. export interface CreateReducer<State> extends AddMapper<State> {
  12. create: () => Reducer<State, ActionOf<any>>;
  13. }
  14. export const reducerFactory = <State>(initialState: State): AddMapper<State> => {
  15. const allMappers: { [key: string]: Mapper<State, any> } = {};
  16. const addMapper = <Payload>(config: MapperConfig<State, Payload>): CreateReducer<State> => {
  17. if (allMappers[config.filter.type]) {
  18. throw new Error(`There is already a mapper defined with the type ${config.filter.type}`);
  19. }
  20. allMappers[config.filter.type] = config.mapper;
  21. return instance;
  22. };
  23. const create = (): Reducer<State, ActionOf<any>> => (state: State = initialState, action: ActionOf<any>): State => {
  24. const mapper = allMappers[action.type];
  25. if (mapper) {
  26. return mapper(state, action);
  27. }
  28. return state;
  29. };
  30. const instance: CreateReducer<State> = { addMapper, create };
  31. return instance;
  32. };