actionCreatorFactory.ts 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. import { Action } from 'redux';
  2. const allActionCreators: string[] = [];
  3. export interface ActionOf<Payload> extends Action {
  4. readonly type: string;
  5. readonly payload: Payload;
  6. }
  7. export interface ActionCreator<Payload> {
  8. readonly type: string;
  9. (payload: Payload): ActionOf<Payload>;
  10. }
  11. export interface NoPayloadActionCreator {
  12. readonly type: string;
  13. (): ActionOf<undefined>;
  14. }
  15. export interface ActionCreatorFactory<Payload> {
  16. create: () => ActionCreator<Payload>;
  17. }
  18. export interface NoPayloadActionCreatorFactory {
  19. create: () => NoPayloadActionCreator;
  20. }
  21. export const actionCreatorFactory = <Payload>(type: string): ActionCreatorFactory<Payload> => {
  22. const create = (): ActionCreator<Payload> => {
  23. return Object.assign((payload: Payload): ActionOf<Payload> => ({ type, payload }), { type });
  24. };
  25. if (allActionCreators.some(t => (t && type ? t.toLocaleUpperCase() === type.toLocaleUpperCase() : false))) {
  26. throw new Error(`There is already an actionCreator defined with the type ${type}`);
  27. }
  28. allActionCreators.push(type);
  29. return { create };
  30. };
  31. export const noPayloadActionCreatorFactory = (type: string): NoPayloadActionCreatorFactory => {
  32. const create = (): NoPayloadActionCreator => {
  33. return Object.assign((): ActionOf<undefined> => ({ type, payload: undefined }), { type });
  34. };
  35. if (allActionCreators.some(t => (t && type ? t.toLocaleUpperCase() === type.toLocaleUpperCase() : false))) {
  36. throw new Error(`There is already an actionCreator defined with the type ${type}`);
  37. }
  38. allActionCreators.push(type);
  39. return { create };
  40. };
  41. // Should only be used by tests
  42. export const resetAllActionCreatorTypes = () => (allActionCreators.length = 0);