actionCreatorFactory.ts 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  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. export interface NoPayloadActionCreatorMock extends NoPayloadActionCreator {
  42. calls: number;
  43. }
  44. export const getNoPayloadActionCreatorMock = (creator: NoPayloadActionCreator): NoPayloadActionCreatorMock => {
  45. const mock: NoPayloadActionCreatorMock = Object.assign(
  46. (): ActionOf<undefined> => {
  47. mock.calls++;
  48. return { type: creator.type, payload: undefined };
  49. },
  50. { type: creator.type, calls: 0 }
  51. );
  52. return mock;
  53. };
  54. export const mockActionCreator = (creator: ActionCreator<any>) => {
  55. return Object.assign(jest.fn(), creator);
  56. };
  57. // Should only be used by tests
  58. export const resetAllActionCreatorTypes = () => (allActionCreators.length = 0);