import { Action } from 'redux'; const allActionCreators: string[] = []; export interface ActionOf extends Action { readonly type: string; readonly payload: Payload; } export interface ActionCreator { readonly type: string; (payload: Payload): ActionOf; } export interface NoPayloadActionCreator { readonly type: string; (): ActionOf; } export interface ActionCreatorFactory { create: () => ActionCreator; } export interface NoPayloadActionCreatorFactory { create: () => NoPayloadActionCreator; } export const actionCreatorFactory = (type: string): ActionCreatorFactory => { const create = (): ActionCreator => { return Object.assign((payload: Payload): ActionOf => ({ type, payload }), { type }); }; if (allActionCreators.some(t => (t && type ? t.toLocaleUpperCase() === type.toLocaleUpperCase() : false))) { throw new Error(`There is already an actionCreator defined with the type ${type}`); } allActionCreators.push(type); return { create }; }; export const noPayloadActionCreatorFactory = (type: string): NoPayloadActionCreatorFactory => { const create = (): NoPayloadActionCreator => { return Object.assign((): ActionOf => ({ type, payload: undefined }), { type }); }; if (allActionCreators.some(t => (t && type ? t.toLocaleUpperCase() === type.toLocaleUpperCase() : false))) { throw new Error(`There is already an actionCreator defined with the type ${type}`); } allActionCreators.push(type); return { create }; }; // Should only be used by tests export const resetAllActionCreatorTypes = () => (allActionCreators.length = 0);