my-utils-kit
Version:
A lightweight and type-safe utility library for working with strings, objects, array Performance methods in TypeScript. Includes helpful methods for deep cloning, object transformations, safe access, query string handling, and more — designed for modern J
341 lines (340 loc) • 9.61 kB
JavaScript
export function deepCloneObj(obj) {
if (obj === null || typeof obj !== 'object')
return obj;
if (Array.isArray(obj)) {
return obj.map(deepCloneObj);
}
const clone = {};
for (const key in obj) {
clone[key] = deepCloneObj(obj[key]);
}
return clone;
}
export function deepMerge(target, source) {
const result = { ...target };
for (const key in source) {
if (source.hasOwnProperty(key) &&
typeof source[key] === 'object' &&
source[key] !== null &&
!Array.isArray(source[key])) {
result[key] = deepMerge(result[key] || {}, source[key]);
}
else {
result[key] = source[key];
}
}
return result;
}
export function isEmpty(obj) {
if (Array.isArray(obj))
return false; // or throw error if not allowed
return Object.keys(obj).length === 0;
}
export function pick(obj, keys) {
const res = {};
for (let key of keys) {
res[key] = obj[key];
}
return res;
}
export function omit(obj, keys) {
const res = { ...obj };
for (let key of keys) {
delete res[key];
}
return res;
}
export function flattenObject(obj, parentKey = '', result = {}) {
for (const key in obj) {
if (!obj.hasOwnProperty(key))
continue;
const newKey = parentKey ? `${parentKey}.${key}` : key;
if (typeof obj[key] === 'object' && obj[key] !== null && !Array.isArray(obj[key])) {
flattenObject(obj[key], newKey, result);
}
else {
result[newKey] = obj[key];
}
}
return result;
}
export function unflattenObject(obj) {
const result = {};
for (const key in obj) {
const keys = key.split('.');
let current = result;
keys.forEach((k, index) => {
if (index === keys.length - 1) {
current[k] = obj[key];
}
else {
if (!(k in current)) {
current[k] = {};
}
current = current[k];
}
});
}
return result;
}
export function invertObj(obj) {
const res = {};
for (const key in obj) {
res[String(obj[key])] = key;
}
return res;
}
export function hasKey(obj, key) {
return key in obj;
}
export function getNestedValue(obj, path) {
return path.split('.').reduce((acc, key) => (acc && acc[key] !== undefined ? acc[key] : undefined), obj);
}
export function setNestedValue(obj, path, value) {
const keys = path.split('.');
let current = obj;
for (let i = 0; i < keys.length - 1; i++) {
const key = keys[i];
// If the key doesn't exist or is not an object, create an empty object for it
if (!(key in current) || typeof current[key] !== 'object') {
current[key] = {};
}
current = current[key];
}
const lastKey = keys[keys.length - 1];
current[lastKey] = value;
return true;
}
export function deleteKey(obj, key) {
const newObj = { ...obj };
delete newObj[key];
return newObj;
}
export function deepEqual(obj1, obj2) {
if (obj1 === obj2)
return true;
if (typeof obj1 !== 'object' || typeof obj2 !== 'object' || obj1 === null || obj2 === null) {
return false;
}
const keys1 = Object.keys(obj1);
const keys2 = Object.keys(obj2);
if (keys1.length !== keys2.length) {
return false;
}
for (let key of keys1) {
if (!keys2.includes(key)) {
return false;
}
if (!deepEqual(obj1[key], obj2[key])) {
return false;
}
}
return true;
}
export function getDeepObjectSize(obj) {
let size = 0;
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
size++;
if (typeof obj[key] === 'object' && obj[key] !== null) {
size += getDeepObjectSize(obj[key]);
}
}
}
return size;
}
export function transformObjectKeys(obj, transformFn) {
const result = {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
const newKey = transformFn(key);
result[newKey] = obj[key];
}
}
return result;
}
export function transformObjectValues(obj, transformFn) {
const result = {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
result[key] = transformFn(obj[key]); // Apply transform export function to the value
}
}
return result;
}
export function objectToQueryString(obj) {
return new URLSearchParams(obj).toString();
}
export function queryStringToObject(queryString) {
const params = new URLSearchParams(queryString);
const result = {};
const entries = params.entries();
for (const [key, value] of entries) {
result[key] = value;
}
return result;
}
export function deepFreeze(obj) {
Object.freeze(obj);
Object.keys(obj).forEach(key => {
const value = obj[key];
if (value && typeof value === 'object') {
deepFreeze(value);
}
});
}
export function seal(obj) {
Object.seal(obj);
}
export function deepSeal(obj) {
Object.seal(obj);
Object.keys(obj).forEach(key => {
const value = obj[key];
if (value && typeof value === 'object') {
deepSeal(value);
}
});
}
export function deepIsFrozen(obj) {
if (!Object.isFrozen(obj))
return false;
// Check for nested objects
return Object.keys(obj).every(key => {
const value = obj[key];
return !(value && typeof value === 'object') || deepIsFrozen(value);
});
}
export function deepIsSealed(obj) {
if (!Object.isSealed(obj))
return false;
// Check for nested objects
return Object.keys(obj).every(key => {
const value = obj[key];
return !(value && typeof value === 'object') || deepIsSealed(value);
});
}
export function hasDeepKey(obj, key) {
if (key in obj)
return true;
for (const k in obj) {
if (obj.hasOwnProperty(k) && typeof obj[k] === 'object' && obj[k] !== null) {
if (hasDeepKey(obj[k], key)) {
return true;
}
}
}
return false;
}
export function isPlainObject(value) {
return Object.prototype.toString.call(value) === '[object Object]';
}
export class TypeUtils {
static isNumber(value) {
return typeof value === 'number';
}
static isString(value) {
return typeof value === 'string';
}
static isBoolean(value) {
return typeof value === 'boolean';
}
static isObject(value) {
return value !== null && typeof value === 'object' && !Array.isArray(value);
}
static isArray(value) {
return Array.isArray(value);
}
static isFunction(value) {
return typeof value === 'function';
}
static isNull(value) {
return value === null;
}
static isUndefined(value) {
return typeof value === 'undefined';
}
static isSymbol(value) {
return typeof value === 'symbol';
}
static isPlainObject(value) {
return value !== null && typeof value === 'object' && Object.getPrototypeOf(value) === Object.prototype;
}
static isDate(value) {
return Object.prototype.toString.call(value) === '[object Date]';
}
static isRegExp(value) {
return Object.prototype.toString.call(value) === '[object RegExp]';
}
static isInstanceOf(value, constructor) {
return value instanceof constructor;
}
static getType(value) {
return Object.prototype.toString.call(value).slice(8, -1); // Returns the internal class name (e.g., "Array", "Object", "Date")
}
}
export function isSubset(obj1, obj2) {
for (let key in obj1) {
if (!(key in obj2) || obj1[key] !== obj2[key]) {
return false;
}
}
return true;
}
export function groupByKeys(arr, keys) {
return arr.reduce((acc, obj) => {
const groupKey = keys.map(key => obj[key]).join('|'); // Use a separator
if (!acc[groupKey]) {
acc[groupKey] = [];
}
acc[groupKey].push(obj);
return acc;
}, {});
}
export function arrayToObject(arr, key) {
return arr.reduce((acc, obj) => {
const keyValue = String(obj[key]);
acc[keyValue] = obj;
return acc;
}, {});
}
export function getUniqueByKey(arr, key) {
const seen = new Map();
for (const item of arr) {
const keyValue = String(item[key]);
if (!seen.has(keyValue)) {
seen.set(keyValue, item);
}
}
return Array.from(seen.values());
}
export function shallowCopy(obj) {
return { ...obj };
}
export function intersectObjects(obj1, obj2) {
const result = {};
for (const key in obj1) {
if (obj2.hasOwnProperty(key) && obj1[key] === obj2[key]) {
result[key] = obj1[key];
}
}
return result;
}
export function diffObjects(obj1, obj2) {
const result = {};
const allKeys = new Set([...Object.keys(obj1), ...Object.keys(obj2)]);
for (const key of allKeys) {
if (obj1[key] !== obj2[key]) {
result[key] = obj1[key] !== undefined ? obj1[key] : obj2[key];
}
}
return result;
}
export function mapObjectValues(obj, callback) {
const result = {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
result[key] = callback(obj[key], key, obj);
}
}
return result;
}