function isArray(array) {
  return Array.isArray(array);
}
function isString(str) {
  return typeof str === "string";
}
function isObject(obj) {
  return typeof obj === "object" && obj !== null && !Array.isArray(obj) && !(obj instanceof RegExp) && !(obj instanceof Date);
}
function isNumber(obj) {
  return typeof obj === "number" && !isNaN(obj);
}
function isIterable(obj) {
  return !!obj && typeof obj[Symbol.iterator] === "function";
}
function isBoolean(obj) {
  return obj === true || obj === false;
}
function isUndefined(obj) {
  return typeof obj === "undefined";
}
function isDefined(arg) {
  return !isUndefinedOrNull(arg);
}
function isUndefinedOrNull(obj) {
  return isUndefined(obj) || obj === null;
}
function assertType(condition, type) {
  if (!condition) {
    throw new Error(type ? `Unexpected type, expected '${type}'` : "Unexpected type");
  }
}
function assertIsDefined(arg) {
  if (isUndefinedOrNull(arg)) {
    throw new Error("Assertion Failed: argument is undefined or null");
  }
  return arg;
}
function isFunction(obj) {
  return typeof obj === "function";
}
function validateConstraints(args, constraints) {
  const len = Math.min(args.length, constraints.length);
  for (let i = 0; i < len; i++) {
    validateConstraint(args[i], constraints[i]);
  }
}
function validateConstraint(arg, constraint) {
  if (isString(constraint)) {
    if (typeof arg !== constraint) {
      throw new Error(`argument does not match constraint: typeof ${constraint}`);
    }
  } else if (isFunction(constraint)) {
    try {
      if (arg instanceof constraint) {
        return;
      }
    } catch (_a) {
    }
    if (!isUndefinedOrNull(arg) && arg.constructor === constraint) {
      return;
    }
    if (constraint.length === 1 && constraint.call(void 0, arg) === true) {
      return;
    }
    throw new Error(`argument does not match one of these constraints: arg instanceof constraint, arg.constructor === constraint, nor constraint(arg) === true`);
  }
}
function getAllPropertyNames(obj) {
  let res = [];
  let proto = Object.getPrototypeOf(obj);
  while (Object.prototype !== proto) {
    res = res.concat(Object.getOwnPropertyNames(proto));
    proto = Object.getPrototypeOf(proto);
  }
  return res;
}
function getAllMethodNames(obj) {
  const methods = [];
  for (const prop of getAllPropertyNames(obj)) {
    if (typeof obj[prop] === "function") {
      methods.push(prop);
    }
  }
  return methods;
}
function createProxyObject(methodNames, invoke) {
  const createProxyMethod = (method) => {
    return function() {
      const args = Array.prototype.slice.call(arguments, 0);
      return invoke(method, args);
    };
  };
  let result = {};
  for (const methodName of methodNames) {
    result[methodName] = createProxyMethod(methodName);
  }
  return result;
}
function withNullAsUndefined(x) {
  return x === null ? void 0 : x;
}
function assertNever(value, message = "Unreachable") {
  throw new Error(message);
}
export {
  assertIsDefined,
  assertNever,
  assertType,
  createProxyObject,
  getAllMethodNames,
  getAllPropertyNames,
  isArray,
  isBoolean,
  isDefined,
  isFunction,
  isIterable,
  isNumber,
  isObject,
  isString,
  isUndefined,
  isUndefinedOrNull,
  validateConstraint,
  validateConstraints,
  withNullAsUndefined
};
