/** * Returns the object type of the given payload * * @param {*} payload * @returns {string} */ function getType(payload) { return Object.prototype.toString.call(payload).slice(8, -1); } /** * Returns whether the payload is undefined * * @param {*} payload * @returns {payload is undefined} */ function isUndefined(payload) { return getType(payload) === 'Undefined'; } /** * Returns whether the payload is null * * @param {*} payload * @returns {payload is null} */ function isNull(payload) { return getType(payload) === 'Null'; } /** * Returns whether the payload is a plain JavaScript object (excluding special classes or objects with other prototypes) * * @param {*} payload * @returns {payload is PlainObject} */ function isPlainObject(payload) { if (getType(payload) !== 'Object') return false; return payload.constructor === Object && Object.getPrototypeOf(payload) === Object.prototype; } /** * Returns whether the payload is a plain JavaScript object (excluding special classes or objects with other prototypes) * * @param {*} payload * @returns {payload is PlainObject} */ function isObject(payload) { return isPlainObject(payload); } /** * Returns whether the payload is a an empty object (excluding special classes or objects with other prototypes) * * @param {*} payload * @returns {payload is { [K in any]: never }} */ function isEmptyObject(payload) { return isPlainObject(payload) && Object.keys(payload).length === 0; } /** * Returns whether the payload is a an empty object (excluding special classes or objects with other prototypes) * * @param {*} payload * @returns {payload is PlainObject} */ function isFullObject(payload) { return isPlainObject(payload) && Object.keys(payload).length > 0; } /** * Returns whether the payload is an any kind of object (including special classes or objects with different prototypes) * * @param {*} payload * @returns {payload is PlainObject} */ function isAnyObject(payload) { return getType(payload) === 'Object'; } /** * Returns whether the payload is an object like a type passed in < > * * Usage: isObjectLike<{id: any}>(payload) // will make sure it's an object and has an `id` prop. * * @template T this must be passed in < > * @param {*} payload * @returns {payload is T} */ function isObjectLike(payload) { return isAnyObject(payload); } /** * Returns whether the payload is a function (regular or async) * * @param {*} payload * @returns {payload is AnyFunction} */ function isFunction(payload) { return typeof payload === 'function'; } /** * Returns whether the payload is an array * * @param {any} payload * @returns {payload is any[]} */ function isArray(payload) { return getType(payload) === 'Array'; } /** * Returns whether the payload is a an array with at least 1 item * * @param {*} payload * @returns {payload is any[]} */ function isFullArray(payload) { return isArray(payload) && payload.length > 0; } /** * Returns whether the payload is a an empty array * * @param {*} payload * @returns {payload is []} */ function isEmptyArray(payload) { return isArray(payload) && payload.length === 0; } /** * Returns whether the payload is a string * * @param {*} payload * @returns {payload is string} */ function isString(payload) { return getType(payload) === 'String'; } /** * Returns whether the payload is a string, BUT returns false for '' * * @param {*} payload * @returns {payload is string} */ function isFullString(payload) { return isString(payload) && payload !== ''; } /** * Returns whether the payload is '' * * @param {*} payload * @returns {payload is string} */ function isEmptyString(payload) { return payload === ''; } /** * Returns whether the payload is a number (but not NaN) * * This will return `false` for `NaN`!! * * @param {*} payload * @returns {payload is number} */ function isNumber(payload) { return getType(payload) === 'Number' && !isNaN(payload); } /** * Returns whether the payload is a boolean * * @param {*} payload * @returns {payload is boolean} */ function isBoolean(payload) { return getType(payload) === 'Boolean'; } /** * Returns whether the payload is a regular expression (RegExp) * * @param {*} payload * @returns {payload is RegExp} */ function isRegExp(payload) { return getType(payload) === 'RegExp'; } /** * Returns whether the payload is a Map * * @param {*} payload * @returns {payload is Map} */ function isMap(payload) { return getType(payload) === 'Map'; } /** * Returns whether the payload is a WeakMap * * @param {*} payload * @returns {payload is WeakMap} */ function isWeakMap(payload) { return getType(payload) === 'WeakMap'; } /** * Returns whether the payload is a Set * * @param {*} payload * @returns {payload is Set} */ function isSet(payload) { return getType(payload) === 'Set'; } /** * Returns whether the payload is a WeakSet * * @param {*} payload * @returns {payload is WeakSet} */ function isWeakSet(payload) { return getType(payload) === 'WeakSet'; } /** * Returns whether the payload is a Symbol * * @param {*} payload * @returns {payload is symbol} */ function isSymbol(payload) { return getType(payload) === 'Symbol'; } /** * Returns whether the payload is a Date, and that the date is valid * * @param {*} payload * @returns {payload is Date} */ function isDate(payload) { return getType(payload) === 'Date' && !isNaN(payload); } /** * Returns whether the payload is a Blob * * @param {*} payload * @returns {payload is Blob} */ function isBlob(payload) { return getType(payload) === 'Blob'; } /** * Returns whether the payload is a File * * @param {*} payload * @returns {payload is File} */ function isFile(payload) { return getType(payload) === 'File'; } /** * Returns whether the payload is a Promise * * @param {*} payload * @returns {payload is Promise} */ function isPromise(payload) { return getType(payload) === 'Promise'; } /** * Returns whether the payload is an Error * * @param {*} payload * @returns {payload is Error} */ function isError(payload) { return getType(payload) === 'Error'; } /** * Returns whether the payload is literally the value `NaN` (it's `NaN` and also a `number`) * * @param {*} payload * @returns {payload is typeof NaN} */ function isNaNValue(payload) { return getType(payload) === 'Number' && isNaN(payload); } /** * Returns whether the payload is a primitive type (eg. Boolean | Null | Undefined | Number | String | Symbol) * * @param {*} payload * @returns {(payload is boolean | null | undefined | number | string | symbol)} */ function isPrimitive(payload) { return (isBoolean(payload) || isNull(payload) || isUndefined(payload) || isNumber(payload) || isString(payload) || isSymbol(payload)); } /** * Returns true whether the payload is null or undefined * * @param {*} payload * @returns {(payload is null | undefined)} */ var isNullOrUndefined = isOneOf(isNull, isUndefined); function isOneOf(a, b, c, d, e) { return function (value) { return a(value) || b(value) || (!!c && c(value)) || (!!d && d(value)) || (!!e && e(value)); }; } /** * Does a generic check to check that the given payload is of a given type. * In cases like Number, it will return true for NaN as NaN is a Number (thanks javascript!); * It will, however, differentiate between object and null * * @template T * @param {*} payload * @param {T} type * @throws {TypeError} Will throw type error if type is an invalid type * @returns {payload is T} */ function isType(payload, type) { if (!(type instanceof Function)) { throw new TypeError('Type must be a function'); } if (!Object.prototype.hasOwnProperty.call(type, 'prototype')) { throw new TypeError('Type is not a class'); } // Classes usually have names (as functions usually have names) var name = type.name; return getType(payload) === name || Boolean(payload && payload.constructor === type); } export { getType, isAnyObject, isArray, isBlob, isBoolean, isDate, isEmptyArray, isEmptyObject, isEmptyString, isError, isFile, isFullArray, isFullObject, isFullString, isFunction, isMap, isNaNValue, isNull, isNullOrUndefined, isNumber, isObject, isObjectLike, isOneOf, isPlainObject, isPrimitive, isPromise, isRegExp, isSet, isString, isSymbol, isType, isUndefined, isWeakMap, isWeakSet };