reducerFactory.ts 1.4 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 allMapperConfigs: Array<MapperConfig<State, any>> = [];
  16. const addMapper = <Payload>(config: MapperConfig<State, Payload>): CreateReducer<State> => {
  17. if (allMapperConfigs.some(c => c.filter.type === config.filter.type)) {
  18. throw new Error(`There is already a Mappers defined with the type ${config.filter.type}`);
  19. }
  20. allMapperConfigs.push(config);
  21. return instance;
  22. };
  23. const create = (): Reducer<State, ActionOf<any>> => (state: State = initialState, action: ActionOf<any>): State => {
  24. const mapperConfig = allMapperConfigs.filter(config => config.filter.type === action.type)[0];
  25. if (mapperConfig) {
  26. return mapperConfig.mapper(state, action);
  27. }
  28. return state;
  29. };
  30. const instance: CreateReducer<State> = { addMapper, create };
  31. return instance;
  32. };