Sfoglia il codice sorgente

Fixed another type of fluent reducerFactory

Hugo Häggmark 6 anni fa
parent
commit
7e64ee8225
1 ha cambiato i file con 93 aggiunte e 1 eliminazioni
  1. 93 1
      public/app/core/redux/reducerFactory.ts

+ 93 - 1
public/app/core/redux/reducerFactory.ts

@@ -1,4 +1,4 @@
-import { ActionOf, ActionCreator } from './actionCreatorFactory';
+import { ActionOf, ActionCreator, actionCreatorFactory } from './actionCreatorFactory';
 import { Reducer } from 'redux';
 import { Reducer } from 'redux';
 
 
 export type Mapper<State, Payload> = (state: State, action: ActionOf<Payload>) => State;
 export type Mapper<State, Payload> = (state: State, action: ActionOf<Payload>) => State;
@@ -43,3 +43,95 @@ export const reducerFactory = <State>(initialState: State): AddMapper<State> =>
 
 
   return instance;
   return instance;
 };
 };
+
+/** Another type of fluent reducerFactory */
+
+export interface FilterWith<State> {
+  filterWith: <Payload>(actionCreator: ActionCreator<Payload>) => MapTo<State, Payload>;
+}
+
+export interface OrFilterWith<State> {
+  orFilterWith: <Payload>(actionCreator: ActionCreator<Payload>) => MapTo<State, Payload>;
+}
+
+export interface MapTo<State, Payload> {
+  mapTo: (mapper: Mapper<State, Payload>) => CreateReducerEx<State>;
+}
+
+export interface CreateReducerEx<State> extends OrFilterWith<State> {
+  create: () => Reducer<State, ActionOf<any>>;
+}
+
+export const reducerFactoryEx = <State>(initialState: State): FilterWith<State> => {
+  const allMapperConfigs: Array<MapperConfig<State, any>> = [];
+
+  const innerMapTo = (actionCreator: ActionCreator<any>, mapper: Mapper<State, any>): CreateReducerEx<State> => {
+    allMapperConfigs.filter(config => config.filter.type === actionCreator.type)[0].mapper = mapper;
+
+    return instance;
+  };
+
+  const filterWith = <Payload>(actionCreator: ActionCreator<Payload>): MapTo<State, Payload> => {
+    if (allMapperConfigs.some(c => c.filter.type === actionCreator.type)) {
+      throw new Error(`There is already a mapper defined with the type ${actionCreator.type}`);
+    }
+
+    allMapperConfigs.push({ filter: actionCreator, mapper: null });
+
+    const mapTo = <Payload>(mapper: Mapper<State, Payload>): CreateReducerEx<State> => {
+      innerMapTo(actionCreator, mapper);
+
+      return instance;
+    };
+
+    return { mapTo };
+  };
+
+  const orFilterWith = <Payload>(actionCreator: ActionCreator<Payload>): MapTo<State, Payload> => {
+    if (allMapperConfigs.some(c => c.filter.type === actionCreator.type)) {
+      throw new Error(`There is already a mapper defined with the type ${actionCreator.type}`);
+    }
+
+    allMapperConfigs.push({ filter: actionCreator, mapper: null });
+
+    const mapTo = <Payload>(mapper: Mapper<State, Payload>): CreateReducerEx<State> => {
+      innerMapTo(actionCreator, mapper);
+
+      return instance;
+    };
+
+    return { mapTo };
+  };
+
+  const create = (): Reducer<State, ActionOf<any>> => (state: State = initialState, action: ActionOf<any>): State => {
+    const mapperConfig = allMapperConfigs.filter(config => config.filter.type === action.type)[0];
+
+    if (mapperConfig) {
+      return mapperConfig.mapper(state, action);
+    }
+
+    return state;
+  };
+
+  const instance = { filterWith, orFilterWith, create };
+
+  return instance;
+};
+
+interface TestState {
+  data: string[];
+}
+
+const initialState: TestState = {
+  data: [],
+};
+
+const dummyActionCreator = actionCreatorFactory<string>('dummyActionCreator').create();
+const dummyActionCreator2 = actionCreatorFactory<number>('dummyActionCreator2').create();
+
+export const reducerFactoryExReducer = reducerFactoryEx<TestState>(initialState)
+  .filterWith(dummyActionCreator)
+  .mapTo((state, action) => ({ ...state, data: state.data.concat(action.payload) }))
+  .orFilterWith(dummyActionCreator2)
+  .mapTo((state, action) => ({ ...state, data: state.data.concat(`${action.payload}`) }))
+  .create();