UNPKG

@kitiumai/utils-ts

Version:

Comprehensive TypeScript utilities for KitiumAI projects

356 lines 8.86 kB
/** * Object utility functions */ /** * Deep merge objects */ export function deepMerge(target, ...sources) { if (!sources.length) { return target; } const result = { ...target }; for (const source of sources) { for (const key in source) { const sourceValue = source[key]; const targetValue = result[key]; if (isPlainObject(sourceValue) && isPlainObject(targetValue)) { result[key] = deepMerge(targetValue, sourceValue); } else { result[key] = sourceValue; } } } return result; } /** * Deep clone an object */ export function deepClone(obj) { if (obj === null || typeof obj !== 'object') { return obj; } if (obj instanceof Date) { return new Date(obj.getTime()); } if (obj instanceof Array) { return obj.map((item) => deepClone(item)); } if (obj instanceof Set) { return new Set(Array.from(obj).map((item) => deepClone(item))); } if (obj instanceof Map) { return new Map(Array.from(obj.entries()).map(([key, value]) => [deepClone(key), deepClone(value)])); } const cloned = {}; for (const key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { cloned[key] = deepClone(obj[key]); } } return cloned; } /** * Pick specific properties from object */ export function pick(obj, keys) { const result = {}; for (const key of keys) { if (key in obj) { result[key] = obj[key]; } } return result; } /** * Omit specific properties from object */ export function omit(obj, keys) { const result = { ...obj }; for (const key of keys) { delete result[key]; } return result; } /** * Safe deep property access with default value */ // eslint-disable-next-line @typescript-eslint/no-explicit-any export function get(obj, path, defaultValue) { const keys = Array.isArray(path) ? path : path.split('.'); // eslint-disable-next-line @typescript-eslint/no-explicit-any let result = obj; for (const key of keys) { if (result === null || result === undefined) { return defaultValue; } result = result[key]; } return result === undefined ? defaultValue : result; } /** * Safe deep property set */ // eslint-disable-next-line @typescript-eslint/no-explicit-any export function set(obj, path, value) { const keys = Array.isArray(path) ? path : path.split('.'); const lastKey = keys.pop(); if (!lastKey) { return; } let current = obj; for (const key of keys) { if (!(key in current) || typeof current[key] !== 'object') { current[key] = {}; } current = current[key]; } current[lastKey] = value; } /** * Deep strict equality check */ // eslint-disable-next-line @typescript-eslint/no-explicit-any export function isEqual(a, b) { if (a === b) { return true; } if (a === null || a === undefined || b === null || b === undefined) { return false; } if (typeof a !== typeof b) { return false; } if (typeof a !== 'object') { return false; } if (Array.isArray(a) && Array.isArray(b)) { if (a.length !== b.length) { return false; } return a.every((item, index) => isEqual(item, b[index])); } if (Array.isArray(a) || Array.isArray(b)) { return false; } const keysA = Object.keys(a); const keysB = Object.keys(b); if (keysA.length !== keysB.length) { return false; } return keysA.every((key) => isEqual(a[key], b[key])); } /** * Transform object keys */ export function mapKeys(obj, fn) { const result = {}; for (const [key, value] of Object.entries(obj)) { result[fn(key, value)] = value; } return result; } /** * Transform object values */ export function mapValues(obj, fn) { const result = {}; for (const [key, value] of Object.entries(obj)) { result[key] = fn(value, key); } return result; } /** * Check if value is a plain object */ export function isPlainObject(value) { if (typeof value !== 'object' || value === null) { return false; } const proto = Object.getPrototypeOf(value); return proto === Object.prototype || proto === null; } /** * Check if object has property */ // eslint-disable-next-line @typescript-eslint/no-explicit-any export function has(obj, key) { const keys = Array.isArray(key) ? key : [key]; // eslint-disable-next-line @typescript-eslint/no-explicit-any let current = obj; for (const k of keys) { if (current === null || current === undefined || !(k in current)) { return false; } current = current[k]; } return true; } /** * Invert object keys and values */ export function invert(obj) { const result = {}; for (const [key, value] of Object.entries(obj)) { result[value] = key; } return result; } /** * Fill missing properties with defaults * * @template T - The type of the target object * @param target - The target object * @param sources - Source objects with default values * @returns A new object with defaults applied * * @example * ```ts * defaults({ a: 1 }, { b: 2, c: 3 }) // { a: 1, b: 2, c: 3 } * ``` */ export function defaults(target, ...sources) { const result = { ...target }; for (const source of sources) { for (const key in source) { if (!(key in result)) { result[key] = source[key]; } } } return result; } /** * Fill missing properties with defaults (deep merge) * * @template T - The type of the target object * @param target - The target object * @param sources - Source objects with default values * @returns A new object with deep defaults applied * * @example * ```ts * defaultsDeep({ a: { b: 1 } }, { a: { c: 2 } }) // { a: { b: 1, c: 2 } } * ``` */ export function defaultsDeep(target, ...sources) { const result = { ...target }; for (const source of sources) { for (const key in source) { const sourceValue = source[key]; const targetValue = result[key]; if (isPlainObject(sourceValue) && isPlainObject(targetValue)) { result[key] = defaultsDeep(targetValue, sourceValue); } else if (!(key in result)) { result[key] = sourceValue; } } } return result; } /** * Get all keys of an object (type-safe) * * @template T - The type of the object * @param obj - The object * @returns An array of keys * * @example * ```ts * keys({ a: 1, b: 2 }) // ['a', 'b'] * ``` */ export function keys(obj) { return Object.keys(obj); } /** * Get all values of an object (type-safe) * * @template T - The type of the object * @param obj - The object * @returns An array of values * * @example * ```ts * values({ a: 1, b: 2 }) // [1, 2] * ``` */ export function values(obj) { return Object.values(obj); } /** * Get all entries of an object (type-safe) * * @template T - The type of the object * @param obj - The object * @returns An array of [key, value] pairs * * @example * ```ts * entries({ a: 1, b: 2 }) // [['a', 1], ['b', 2]] * ``` */ export function entries(obj) { return Object.entries(obj); } /** * Create an object from an array of [key, value] pairs * * @template T - The type of values * @param pairs - Array of [key, value] pairs * @returns An object created from the pairs * * @example * ```ts * fromPairs([['a', 1], ['b', 2]]) // { a: 1, b: 2 } * ``` */ export function fromPairs(pairs) { const result = {}; for (const [key, value] of pairs) { result[key] = value; } return result; } /** * Convert an object to an array of [key, value] pairs * * @template T - The type of values * @param obj - The object to convert * @returns An array of [key, value] pairs * * @example * ```ts * toPairs({ a: 1, b: 2 }) // [['a', 1], ['b', 2]] * ``` */ export function toPairs(obj) { return Object.entries(obj); } /** * Get the size of a collection (array, string, or object) * * @param value - The value to get size of * @returns The size of the collection * * @example * ```ts * size([1, 2, 3]) // 3 * size('hello') // 5 * size({ a: 1, b: 2 }) // 2 * ``` */ export function size(value) { if (value === null || value === undefined) { return 0; } if (Array.isArray(value) || typeof value === 'string') { return value.length; } if (typeof value === 'object') { return Object.keys(value).length; } return 0; } //# sourceMappingURL=object.js.map