import { toString, objectProto, hasOwnProperty } from "./object"; import { getType } from "./get"; export function isType(val: any, type: string): boolean { return toString.call(val) === '[object ' + type + ']' } export function isArray(val: any): val is Array { return Array.isArray ? Array.isArray(val) : isType(val, 'Array'); } export function isArrayLike(val: any): boolean { return val !== null && typeof val !== 'function' && isFinite(val.length); } export function isString(val: any): val is string { return isType(val, 'String'); } export function isNumber(val: any): val is number { return isType(val, 'Number'); } export function isInteger(val: any): val is number { return isNumber(val) && val % 1 === 0; } export function isDecimal(val: any): val is number { return isNumber(val) && val % 1 !== 0; } export function isNegative(val: any): val is number { return isNumber(val) && val < 0; } export function isPositive(val: any): val is number { return isNumber(val) && val > 0; } export function isOdd(val: any): val is number { return isNumber(val) && val % 2 !== 0; } export function isEven(val: any): val is number { return isNumber(val) && val % 2 === 0; } export function isBoolean(val: any): val is boolean { return isType(val, 'Boolean') } export function isDate(val: any): val is Date { return isType(val, 'Date') } export function isFunction(val: any): val is Function { return isType(val, 'Function') } export function isError(val: any): val is Error { return isType(val, 'Error') } export function isUndefined(val: any): val is undefined { return val === undefined; } export function isNull(val: any): val is null { return val === null; } export function isNil(val: any): val is null | undefined { return isUndefined(val) || isNull(val) } export function isObjectLike(val: any): val is object { return typeof val === 'object' && val !== null; } export function isPlainObject(val: any): val is object { if (!isObjectLike(val) || !isType(val, 'Object')) { return false; } if (Object.getPrototypeOf(val) === null) { return true; } let proto = val; while (Object.getPrototypeOf(proto) !== null) { proto = Object.getPrototypeOf(proto); } return Object.getPrototypeOf(val) === proto; } export function isPrototype(val: any): boolean { const Ctor = val && val.constructor; const proto = (typeof Ctor === 'function' && Ctor.prototype) || objectProto; return val === proto; } export function isRegExp(val: any): val is RegExp { return isType(val, 'RegExp') } export function isEmpty(val: any): boolean { if (isNil(val)) { return true; } if (isArrayLike(val)) { return !val.length; } const type = getType(val); if (type === 'Map' || type === 'Set') { return !val.size; } if (isPrototype(val)) { return !Object.keys(val).length; } for (const key in val) { if (hasOwnProperty.call(val, key)) { return false; } } return true; } export function isEqual(value: any, other: any): boolean { if (value === other) { return true; } if (!value || !other) { return false; } if (isString(value) || isString(other)) { return false; } if (isArrayLike(value) || isArrayLike(other)) { if (value.length !== other.length) { return false; } let rst = true; for (let i = 0; i < value.length; i++) { rst = isEqual(value[i], other[i]); if (!rst) { break; } } return rst; } if (isObjectLike(value) || isObjectLike(other)) { const valueKeys = Object.keys(value); const otherKeys = Object.keys(other); if (valueKeys.length !== otherKeys.length) { return false; } let rst = true; for (let i = 0; i < valueKeys.length; i++) { rst = isEqual(value[valueKeys[i]], other[valueKeys[i]]); if (!rst) { break; } } return rst; } return false; } export function isEqualWith(value: T, other: T, fn: (v1: T, v2: T) => boolean): boolean { if (!isFunction(fn)) { return isEqual(value, other); } return !!fn(value, other); }