super-utils-plus
Version:
A superior alternative to Lodash with improved performance, TypeScript support, and developer experience
124 lines (123 loc) • 3.76 kB
JavaScript
/**
* Type checking functions with improved TypeScript support
*/
/**
* Checks if value is null or undefined
*/
export const isNil = (value) => value === null || value === undefined;
/**
* Checks if value is undefined
*/
export const isUndefined = (value) => value === undefined;
/**
* Checks if value is null
*/
export const isNull = (value) => value === null;
/**
* Checks if value is a number
* Unlike Lodash, this correctly returns false for NaN
*/
export const isNumber = (value) => typeof value === 'number' && !Number.isNaN(value);
/**
* Checks if value is a string
*/
export const isString = (value) => typeof value === 'string';
/**
* Checks if value is a boolean
*/
export const isBoolean = (value) => typeof value === 'boolean';
/**
* Checks if value is a function
*/
// eslint-disable-next-line @typescript-eslint/ban-types
export const isFunction = (value) => typeof value === 'function';
/**
* Checks if value is an array
*/
export const isArray = Array.isArray;
/**
* Checks if value is an object (excluding null)
* This is different from Lodash as it doesn't consider arrays as objects
*/
export const isObject = (value) => value !== null && typeof value === 'object' && !isArray(value);
/**
* Checks if value is a plain object (created by Object constructor or object literal)
*/
export const isPlainObject = (value) => {
if (value === null || typeof value !== 'object')
return false;
const proto = Object.getPrototypeOf(value);
return proto === null || proto === Object.prototype;
};
/**
* Checks if value is a Date object
*/
export const isDate = (value) => value instanceof Date;
/**
* Checks if value is a RegExp object
*/
export const isRegExp = (value) => value instanceof RegExp;
/**
* Checks if value is a valid finite number
*/
export const isFinite = (value) => isNumber(value) && Number.isFinite(value);
/**
* Checks if value is an integer
*/
export const isInteger = (value) => isNumber(value) && Number.isInteger(value);
/**
* Checks if value is NaN
*/
export const isNaN = (value) => Number.isNaN(value);
/**
* Checks if value is empty
* Works with strings, arrays, objects, maps, sets
*/
export const isEmpty = (value) => {
if (isNil(value))
return true;
if (isString(value) || isArray(value))
return value.length === 0;
if (value instanceof Map || value instanceof Set)
return value.size === 0;
if (isObject(value))
return Object.keys(value).length === 0;
return false;
};
/**
* Checks if two values are equal (deep comparison)
*/
export const isEqual = (value, other) => {
// Same reference or both NaN
if (value === other || (isNaN(value) && isNaN(other)))
return true;
// Different types or null/undefined
if (isNil(value) || isNil(other) || typeof value !== typeof other)
return false;
// Compare arrays
if (isArray(value) && isArray(other)) {
if (value.length !== other.length)
return false;
return value.every((item, i) => isEqual(item, other[i]));
}
// Compare dates
if (isDate(value) && isDate(other)) {
return value.getTime() === other.getTime();
}
// Compare regexps
if (isRegExp(value) && isRegExp(other)) {
return value.toString() === other.toString();
}
// Compare objects
if (isObject(value) && isObject(other)) {
const valueKeys = Object.keys(value);
const otherKeys = Object.keys(other);
if (valueKeys.length !== otherKeys.length)
return false;
return valueKeys.every(key => {
return Object.prototype.hasOwnProperty.call(other, key) &&
isEqual(value[key], other[key]);
});
}
return false;
};