(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
    typeof define === 'function' && define.amd ? define(['exports'], factory) :
    (global = global || self, factory(global.TypesafeActions = {}));
}(this, (function (exports) { 'use strict';

    function checkIsEmpty(arg) {
      return arg == null;
    }
    function throwIsEmpty(argPosition) {
      throw new Error("Argument " + argPosition + " is empty.");
    }
    function checkValidActionCreator(arg) {
      return typeof arg === 'function' && 'getType' in arg;
    }
    function checkInvalidActionCreator(arg) {
      return !checkValidActionCreator(arg);
    }
    function throwInvalidActionCreator(argPosition) {
      throw new Error("Argument " + argPosition + " is invalid, it should be an action-creator instance from \"typesafe-actions\"");
    }
    function checkInvalidActionCreatorInArray(arg, idx) {
      if (arg == null) {
        throw new Error("Argument contains array with empty element at index " + idx);
      } else if (arg.getType == null) {
        throw new Error("Argument contains array with invalid element at index " + idx + ", it should be an action-creator instance from \"typesafe-actions\"");
      }
    }
    function checkValidActionType(arg) {
      return typeof arg === 'string' || typeof arg === 'symbol';
    }
    function checkInvalidActionType(arg) {
      return !checkValidActionType(arg);
    }
    function throwInvalidActionType(argPosition) {
      throw new Error("Argument " + argPosition + " is invalid, it should be an action type of type: string | symbol");
    }
    function checkInvalidActionTypeInArray(arg, idx) {
      if (arg == null) {
        throw new Error("Argument contains array with empty element at index " + idx);
      } else if (typeof arg !== 'string' && typeof arg !== 'symbol') {
        throw new Error("Argument contains array with invalid element at index " + idx + ", it should be of type: string | symbol");
      }
    }
    function throwInvalidActionTypeOrActionCreator(argPosition) {
      throw new Error("Argument " + argPosition + " is invalid, it should be an action-creator instance from \"typesafe-actions\" or action type of type: string | symbol");
    }

    function action(type, payload, meta, error) {
      if (checkIsEmpty(type)) {
        throwIsEmpty(1);
      }

      if (checkInvalidActionType(type)) {
        throwInvalidActionCreator(1);
      }

      return {
        type: type,
        payload: payload,
        meta: meta,
        error: error
      };
    }

    function createCustomAction(type, createHandler) {
      if (checkIsEmpty(type)) {
        throwIsEmpty(1);
      }

      if (checkInvalidActionType(type)) {
        throwInvalidActionType(1);
      }

      var actionCreator = function actionCreator() {
        var customProps = createHandler != null ? createHandler.apply(void 0, arguments) : undefined;
        return Object.assign({
          type: type
        }, customProps);
      };

      var typeMeta = {
        getType: function getType() {
          return type;
        },
        toString: function toString() {
          return type;
        }
      };
      return Object.assign(actionCreator, typeMeta);
    }

    function createAction(type, payloadCreator, metaCreator) {
      if (checkIsEmpty(type)) {
        throwIsEmpty(1);
      }

      if (checkInvalidActionType(type)) {
        throwInvalidActionType(1);
      }

      return function () {
        return createCustomAction(type, function () {
          var payload = arguments.length <= 0 ? undefined : arguments[0];
          var meta = arguments.length <= 1 ? undefined : arguments[1];

          if (payloadCreator != null || metaCreator != null) {
            payload = payloadCreator != null ? payloadCreator.apply(void 0, arguments) : undefined;
            meta = metaCreator != null ? metaCreator.apply(void 0, arguments) : undefined;
          }

          return Object.assign({}, payload !== undefined && {
            payload: payload
          }, {}, meta !== undefined && {
            meta: meta
          });
        });
      };
    }

    function throwInvalidAsyncActionArgument(argPosition) {
      throw new Error("Argument " + argPosition + " is invalid, it should be an action type of \"string | symbol\" or a tuple of \"[string | symbol, Function, Function?]\"");
    }
    function createAsyncAction(requestArg, successArg, failureArg, cancelArg) {
      var constructor = function constructor() {
        var results = [requestArg, successArg, failureArg, cancelArg].map(function (arg, index) {
          if (Array.isArray(arg)) {
            return createAction(arg[0], arg[1], arg[2])();
          } else if (typeof arg === 'string' || typeof arg === 'symbol') {
            return createAction(arg)();
          } else if (index < 3) {
            throwInvalidAsyncActionArgument(index);
          }
        });
        var request = results[0],
            success = results[1],
            failure = results[2],
            cancel = results[3];
        return {
          request: request,
          success: success,
          failure: failure,
          cancel: cancel
        };
      };

      return constructor;
    }

    function getType(actionCreator) {
      if (checkIsEmpty(actionCreator)) {
        throwIsEmpty(1);
      }

      if (checkInvalidActionCreator(actionCreator)) {
        throwInvalidActionCreator(1);
      }

      return actionCreator.getType();
    }

    function createReducer(initialState, initialHandlers) {
      if (initialHandlers === void 0) {
        initialHandlers = {};
      }

      var handlers = Object.assign({}, initialHandlers);

      var rootReducer = function rootReducer(state, action) {
        if (state === void 0) {
          state = initialState;
        }

        if (handlers.hasOwnProperty(action.type)) {
          var reducer = handlers[action.type];

          if (typeof reducer !== 'function') {
            throw Error("Reducer under \"" + action.type + "\" key is not a valid reducer");
          }

          return reducer(state, action);
        } else {
          return state;
        }
      };

      var reducerHandler = function reducerHandler(singleOrMultipleCreatorsAndTypes, reducer) {
        var creatorsAndTypes = Array.isArray(singleOrMultipleCreatorsAndTypes) ? singleOrMultipleCreatorsAndTypes : [singleOrMultipleCreatorsAndTypes];
        var newHandlers = {};
        creatorsAndTypes.map(function (acOrType, index) {
          return checkValidActionCreator(acOrType) ? getType(acOrType) : checkValidActionType(acOrType) ? acOrType : throwInvalidActionTypeOrActionCreator(index + 1);
        }).forEach(function (type) {
          return newHandlers[type] = reducer;
        });
        return createReducer(initialState, Object.assign({}, handlers, {}, newHandlers));
      };

      var chainApi = Object.assign(rootReducer, {
        handlers: Object.assign({}, handlers),
        handleAction: reducerHandler,
        handleType: reducerHandler
      });
      return chainApi;
    }

    function isOfType(actionTypeOrTypes, action) {
      if (checkIsEmpty(actionTypeOrTypes)) {
        throwIsEmpty(1);
      }

      var actionTypes = Array.isArray(actionTypeOrTypes) ? actionTypeOrTypes : [actionTypeOrTypes];
      actionTypes.forEach(checkInvalidActionTypeInArray);

      var assertFn = function assertFn(_action) {
        return actionTypes.includes(_action.type);
      };

      if (action === undefined) {
        return assertFn;
      }

      return assertFn(action);
    }

    function isActionOf(actionCreatorOrCreators, action) {
      if (checkIsEmpty(actionCreatorOrCreators)) {
        throwIsEmpty(1);
      }

      var actionCreators = Array.isArray(actionCreatorOrCreators) ? actionCreatorOrCreators : [actionCreatorOrCreators];
      actionCreators.forEach(checkInvalidActionCreatorInArray);

      var assertFn = function assertFn(_action) {
        return actionCreators.some(function (actionCreator) {
          return _action.type === actionCreator.getType();
        });
      };

      if (action === undefined) {
        return assertFn;
      }

      return assertFn(action);
    }

    function createAction$1(type, createHandler) {
      var actionCreator = createHandler == null ? function () {
        return action(type);
      } : createHandler(action.bind(null, type));
      return Object.assign(actionCreator, {
        getType: function getType() {
          return type;
        },
        toString: function toString() {
          return type;
        }
      });
    }

    function createCustomAction$1(type, createHandler) {
      if (checkIsEmpty(type)) {
        throwIsEmpty(1);
      }

      if (checkInvalidActionType(type)) {
        throwInvalidActionType(1);
      }

      var actionCreator = createHandler != null ? createHandler(type) : function () {
        return {
          type: type
        };
      };
      return Object.assign(actionCreator, {
        getType: function getType() {
          return type;
        },
        toString: function toString() {
          return type;
        }
      });
    }

    function createStandardAction(type) {
      if (checkIsEmpty(type)) {
        throwIsEmpty(1);
      }

      if (checkInvalidActionType(type)) {
        throwInvalidActionType(1);
      }

      function constructor() {
        return createCustomAction$1(type, function (_type) {
          return function (payload, meta) {
            return {
              type: _type,
              payload: payload,
              meta: meta
            };
          };
        });
      }

      function map(fn) {
        return createCustomAction$1(type, function (_type) {
          return function (payload, meta) {
            return Object.assign(fn(payload, meta), {
              type: _type
            });
          };
        });
      }

      return Object.assign(constructor, {
        map: map
      });
    }

    var index = {
      createAction: createAction$1,
      createCustomAction: createCustomAction$1,
      createStandardAction: createStandardAction
    };

    exports.action = action;
    exports.createAction = createAction;
    exports.createAsyncAction = createAsyncAction;
    exports.createCustomAction = createCustomAction;
    exports.createReducer = createReducer;
    exports.deprecated = index;
    exports.getType = getType;
    exports.isActionOf = isActionOf;
    exports.isOfType = isOfType;

})));
//# sourceMappingURL=typesafe-actions.umd.development.js.map
