@resk/core
Version:
An innovative TypeScript framework that empowers developers to build applications with a fully decorator-based architecture for efficient resource management. By combining the power of decorators with a resource-oriented design, DecorRes enhances code cla
497 lines (496 loc) • 20.2 kB
TypeScript
import { IDict, IPrimitive } from "../types";
/**
* Checks if the given variable is a plain object.
*
* A plain object is defined as an object that is created by the Object constructor
* or one that inherits from `Object.prototype`. This function will return false for
* instances of classes, arrays, and other non-plain objects.
*
* @param {any} obj - The variable to check for being a plain object.
*
* @returns {boolean} Returns true if the variable is a plain object, false otherwise.
*
* @example
* ```ts
* // Example with a string
* console.log(isPlainObj("hello")); // Outputs: false
*
* // Example with a plain object
* console.log(isPlainObj({ a: true })); // Outputs: true
*
* // Example with a function
* console.log(isPlainObj(() => true)); // Outputs: false
*
* // Example with an array
* console.log(isPlainObj([1, 2, 3])); // Outputs: false
*
* // Example with a Date object
* console.log(isPlainObj(new Date())); // Outputs: false
*
* // Example with a plain object created using Object.create
* const obj = Object.create(null);
* console.log(isPlainObj(obj)); // Outputs: true
* ```
*/
export declare const isPlainObj: (obj: any) => boolean;
/**
* Clones a source object by returning a non-reference copy of the object.
*
* This function creates a deep copy of the provided object.
* Any nested objects or arrays within the source will also be cloned, ensuring that the
* returned object does not reference the original object.
*
* @template T - The type of the object to clone. This can be any type, including arrays and nested objects.
* @param {T} source - The object to clone. This can be any type, including arrays and nested objects.
*
* @returns {T} A deep cloned copy of the source object. The return type can be
* either an object or an array, depending on the input.
*
* @example
* ```ts
* // Example with a simple object
* const original = { a: 1, b: { c: 2 } };
* const cloned = cloneObject(original);
* console.log(cloned); // Outputs: { a: 1, b: { c: 2 } }
*
* // Modifying the cloned object does not affect the original
* cloned.b.c = 3;
* console.log(original.b.c); // Outputs: 2 (original remains unchanged)
*
* // Example with an array
* const originalArray = [1, 2, { a: 3 }];
* const clonedArray = cloneObject(originalArray);
* console.log(clonedArray); // Outputs: [1, 2, { a: 3 }]
*
* // Modifying the cloned array does not affect the original
* clonedArray[2].a = 4;
* console.log(originalArray[2].a); // Outputs: 3 (original remains unchanged)
*
* // Example with a nested structure
* const complexObject = { a: 1, b: [2, { c: 3 }] };
* const clonedComplex = cloneObject(complexObject);
* console.log(clonedComplex); // Outputs: { a: 1, b: [2, { c: 3 }] }
* ```
*/
export declare function cloneObject<T = any>(source: T): T;
/**
* Determines if the given variable is a plain object.
*
* This function checks whether the provided variable is a plain object, which is defined as an object
* created by the Object constructor or one that inherits from `Object.prototype`. It will return false
* for instances of classes, arrays, and other non-plain objects.
*
* @param {any} obj - The variable to check for being an object.
*
* @returns {boolean} Returns true if the variable is a plain object, false otherwise.
*
* @example
* ```ts
* // Example with a string
* console.log(isObj("hello")); // Outputs: false
*
* // Example with a plain object
* console.log(isObj({ a: true })); // Outputs: true
*
* // Example with an array
* console.log(isObj([1, 2, 3])); // Outputs: false
*
* // Example with a function
* console.log(isObj(() => true)); // Outputs: false
*
* // Example with a Date object
* console.log(isObj(new Date())); // Outputs: false
*
* // Example with a plain object created using Object.create
* const obj = Object.create(null);
* console.log(isObj(obj)); // Outputs: true
* ```
*/
export declare function isObj<T = any>(obj: T): obj is IObject<T>;
type IObject<T = any> = T extends IDict ? T : T extends undefined ? never : any;
/**
* Calculates the size of an object or array.
*
* This function returns the number of own properties of an object or the length of an array.
* If the input is null or not an object, it returns 0.
*
* @param {any} obj - The object or array whose size is to be calculated.
* @param {boolean} [breakOnFirstElementFound=false] - Optional flag to determine if the function should
* return the size immediately upon finding the first property or element.
*
* @returns {number} The size of the object or array. Returns 0 if the input is null or not an object.
*
* @example
* // Example with an object
* const exampleObject = { a: 1, b: 2, c: 3 };
* const size = objectSize(exampleObject);
* console.log(size); // Outputs: 3
*
* @example
* // Example with an array
* const exampleArray = [1, 2, 3, 4];
* const arraySize = objectSize(exampleArray);
* console.log(arraySize); // Outputs: 4
*
* @example
* // Example with breakOnFirstElementFound
* const earlyExitSize = objectSize(exampleObject, true);
* console.log(earlyExitSize); // Outputs: 1, as it returns after the first property
*
* @example
* // Example with a null input
* const nullSize = objectSize(null);
* console.log(nullSize); // Outputs: 0
*
* @example
* // Example with a non-object input
* const nonObjectSize = objectSize(42);
* console.log(nonObjectSize); // Outputs: 0
*/
export declare const objectSize: (obj: any, breakOnFirstElementFound?: boolean) => number;
/**
* Returns a default object based on the provided arguments.
*
* This function takes multiple arguments and returns the first non-empty object found.
* If only one argument is provided, it returns that argument if it is an object; otherwise, it returns an empty object.
* If no valid object is found among the arguments, it returns an empty object.
*
* @param {...any[]} args - The arguments to check for objects.
* @template T - The type of the object to return.
*
* @returns {object} The first non-empty object found among the arguments, or an empty object if none is found.
*
* @example
* ```ts
* // Example with one valid object
* const result1 = defaultObj({ a: 1 });
* console.log(result1); // Outputs: { a: 1 }
*
* // Example with one invalid argument
* const result2 = defaultObj("not an object");
* console.log(result2); // Outputs: {}
*
* // Example with multiple arguments, returning the first non-empty object
* const result3 = defaultObj({}, { b: 2 }, { c: 3 });
* console.log(result3); // Outputs: { b: 2 }
*
* // Example with multiple arguments, returning the last valid object
* const result4 = defaultObj({}, {}, { d: 4 });
* console.log(result4); // Outputs: { d: 4 }
*
* // Example with no valid objects
* const result5 = defaultObj(null, undefined, "string");
* console.log(result5); // Outputs: {}
* ```
*/
export declare function defaultObj<T extends object = any>(...args: any[]): T;
/**
* Declares a global interface extension for the built-in `Object` type.
*/
declare global {
/**
* Interface extension for the built-in `Object` type.
*/
interface Object {
/**
* Clones a source object by returning a non-reference copy of the object.
*
* This method creates a deep clone of the provided object, ensuring that nested objects
* are also cloned, and modifications to the cloned object do not affect the original.
*
* @param {any} obj - The object to clone. This can be any type, including arrays and nested objects.
* @returns {any} The cloned object, which can be an object or an array.
*
* @example
* ```ts
* const original = { a: 1, b: { c: 2 } };
* const cloned = Object.clone(original);
* console.log(cloned); // Outputs: { a: 1, b: { c: 2 } }
*
* cloned.b.c = 3;
* console.log(original.b.c); // Outputs: 2 (original remains unchanged)
* ```
* @template T - The type of the object to clone.
* @param {T} obj - The object to clone.
* @returns {T} A clone of the object.
*/
clone: <T = any>(obj: T) => T;
/**
* Determines the size of an object or array.
*
* This method calculates the number of own enumerable properties in an object or
* the number of elements in an array. If the `breakOnFirstElementFound` parameter
* is set to true, it will return 1 immediately upon finding the first element or property.
*
* @param {any} obj - The object or array to determine the size of.
* @param {boolean} [breakOnFirstElementFound=false] - Whether to return immediately after the first element is found.
* @returns {number} The size of the object or array. Returns 0 if the input is not an object or array.
*
* @example
* ```ts
* const obj = { a: 1, b: 2, c: 3 };
* const size = Object.getSize(obj);
* console.log(size); // Outputs: 3
*
* const arr = [1, 2, 3];
* const arrSize = Object.getSize(arr);
* console.log(arrSize); // Outputs: 3
*
* const singleElementSize = Object.getSize(arr, true);
* console.log(singleElementSize); // Outputs: 1 (returns immediately)
*
* const emptyObjSize = Object.getSize({});
* console.log(emptyObjSize); // Outputs: 0
* ```
*/
getSize: (obj: any, breakOnFirstElementFound?: boolean) => number;
/**
* Flattens a nested object structure into a single-level object with dot/bracket notation keys.
* Handles various data structures including Arrays, Sets, Maps, and plain objects.
* Skips non-primitive values like functions, class instances.
*
* @param {any} obj - The object to flatten
* @param {string} [prefix=''] - The prefix to use for nested keys
* @returns {Record<string, Primitive>} A flattened object with primitive values
*
* @example
* // Basic object flattening
* _flattenObject({
* a: {
* b: 'value',
* c: 42
* }
* })
* // Returns: { 'a.b': 'value', 'a.c': 42 }
*
* @example
* // Array handling
* _flattenObject({
* items: ['a', 'b', { nested: 'value' }]
* })
* // Returns: { 'items[0]': 'a', 'items[1]': 'b', 'items[2].nested': 'value' }
*
* @example
* // Map handling
* _flattenObject({
* map: new Map([
* ['key1', 'value1'],
* ['key2', { nested: 'value2' }]
* ])
* })
* // Returns: { 'map[key1]': 'value1', 'map[key2].nested': 'value2' }
*
* @example
* // Complex nested structure
* _flattenObject({
* array: [1, { a: 2 }],
* set: new Set(['x', { b: 'y' }]),
* map: new Map([['k', { c: 'v' }]]),
* obj: {
* deep: {
* nested: 'value',
* fn: () => {}, // Will be skipped
* date: new Date() // Will be skipped
* }
* }
* })
* // Returns: {
* // 'array[0]': 1,
* // 'array[1].a': 2,
* // 'set[0]': 'x',
* // 'set[1].b': 'y',
* // 'map[k].c': 'v',
* // 'obj.deep.nested': 'value'
* // }
*
* @throws {Error} Will not throw errors, but silently skips non-primitive values
*
* @category Utilities
* @since 1.0.0
*/
flatten(obj: any): Record<string, IPrimitive>;
/**
* Enhanced version of Object.entries that preserves key types in TypeScript inference.
*
* Unlike the standard Object.entries which types all keys as string, this method
* maintains the original key types (string | number | symbol) in TypeScript's type system
* while still following JavaScript's runtime behavior where all keys are strings.
*
* @template T - The object type extending Record<string | number, any>
* @param obj - The object to extract entries from
* @returns Array of key-value tuples with preserved key types in TypeScript
*
* @example
* ```typescript
* const obj = { 1: "one", "foo": "bar", 42: "answer" } as const;
*
* // Standard Object.entries - all keys typed as string
* const standard = Object.entries(obj); // [string, string][]
*
* // Enhanced Object.typedEntries - preserves original key types
* const typed = Object.typedEntries(obj);
* // Type: (["1", "one"] | ["foo", "bar"] | ["42", "answer"])[]
* ```
*
* @remarks
* - Runtime behavior is identical to Object.entries (all keys are strings)
* - Only TypeScript inference is enhanced to remember original key types
* - Works best with objects declared with 'as const' for literal type inference
* - Particularly useful for objects with mixed string and numeric keys
*
* @since 1.0.0
*/
typedEntries<T extends Record<any, unknown> = any>(obj: T): Array<{
[K in keyof T]: [K, T[K]];
}[keyof T]>;
}
}
/**
* Extends an object by merging properties from one or more source objects.
*
* This function takes a target object and one or more source objects, merging the properties
* from the source objects into the target object. If a property exists in both the target
* and a source object, the value from the source object will overwrite the target's value.
* For arrays, the function merges the contents of the arrays, preserving the original order of the elements.
*@template T - The type of the target object.
* @param {T} target - The object to extend. It will receive the new properties.
* @param {...any[]} sources - The source objects to merge into the target. These objects will not be modified.
* @returns {T} The extended target object, which contains properties from the source objects.
*
* @example
* ```ts
* const target = { a: 1, b: 2 };
* const source1 = { b: 3, c: 4 };
* const source2 = { d: 5 };
*
* const extended = extendObj(target, source1, source2);
* console.log(extended); // Outputs: { a: 1, b: 3, c: 4, d: 5 }
* console.log(target); // Outputs: { a: 1, b: 3 } (target is modified)
* ```
* Merges the contents of two or more objects together into the first object.
* Similar to jQuery's $.extend function.
* @remarks
* This function is used to merge the contents of multiple objects into a single object. It takes an optional target object as the first argument and one or more source objects as additional arguments. The function returns the merged object, which is a new object that contains all the properties from the source objects.
*
* If the target object is not provided or is not a plain object, an empty object is returned.
*
* If the target object is a plain object, the function iterates over the sources and copies the properties from each source object to the target object. If a property with the same name already exists in the target object, it is overwritten with the corresponding value from the source object.
*
* If the target object is a plain object, the function iterates over the sources and copies the properties from each source object to the target object. If a property with the same name already exists in the target object, it is overwritten with the corresponding value from the source object.
* For arrays, The function replaces the contents of the arrays, preserving the original order of the elements.
* Empty values like null, undefined, and empty strings are ignored.
*/
export declare function extendObj<T extends Record<string, any> = any>(target: any, ...sources: any[]): T;
/**
* Flattens a nested object structure into a single-level object with dot/bracket notation keys.
* Handles various data structures including Arrays, Sets, Maps, and plain objects.
* Skips non-primitive values like functions, class instances.
*
* @param {any} obj - The object to flatten
* @param {string} [prefix=''] - The prefix to use for nested keys
* @returns {Record<string, Primitive>} A flattened object with primitive values
*
* @example
* // Basic object flattening
* _flattenObject({
* a: {
* b: 'value',
* c: 42
* }
* })
* // Returns: { 'a.b': 'value', 'a.c': 42 }
*
* @example
* // Array handling
* _flattenObject({
* items: ['a', 'b', { nested: 'value' }]
* })
* // Returns: { 'items[0]': 'a', 'items[1]': 'b', 'items[2].nested': 'value' }
*
* @example
* // Map handling
* _flattenObject({
* map: new Map([
* ['key1', 'value1'],
* ['key2', { nested: 'value2' }]
* ])
* })
* // Returns: { 'map[key1]': 'value1', 'map[key2].nested': 'value2' }
*
* @example
* // Complex nested structure
* _flattenObject({
* array: [1, { a: 2 }],
* set: new Set(['x', { b: 'y' }]),
* map: new Map([['k', { c: 'v' }]]),
* obj: {
* deep: {
* nested: 'value',
* fn: () => {}, // Will be skipped
* date: new Date() // Will be skipped
* }
* }
* })
* // Returns: {
* // 'array[0]': 1,
* // 'array[1].a': 2,
* // 'set[0]': 'x',
* // 'set[1].b': 'y',
* // 'map[k].c': 'v',
* // 'obj.deep.nested': 'value'
* // }
*
* @throws {Error} Will not throw errors, but silently skips non-primitive values
*
* @category Utilities
* @since 1.0.0
*/
export declare function flattenObject(obj: any): Record<string, any>;
/**
* Checks if a value is an iterable data structure (Array, Set, Map, WeakMap, WeakSet).
*
* @param {any} value - The value to check
* @returns {boolean} True if the value is an iterable structure, false otherwise
*
* @example
* isIterableStructure([1, 2, 3]) // returns true
* isIterableStructure(new Set([1, 2, 3])) // returns true
* isIterableStructure(new Map()) // returns true
* isIterableStructure({}) // returns false
*/
export declare function isIterableStructure(value: any): boolean;
/**
* Enhanced version of Object.entries that preserves key types in TypeScript inference.
*
* Unlike the standard Object.entries which types all keys as string, this method
* maintains the original key types (string | number | symbol) in TypeScript's type system
* while still following JavaScript's runtime behavior where all keys are strings.
*
* @template T - The object type extending Record<string | number, any>
* @param obj - The object to extract entries from
* @returns Array of key-value tuples with preserved key types in TypeScript
*
* @example
* ```typescript
* const obj = { 1: "one", "foo": "bar", 42: "answer" } as const;
*
* // Standard Object.entries - all keys typed as string
* const standard = Object.entries(obj); // [string, string][]
*
* // Enhanced Object.typedEntries - preserves original key types
* const typed = Object.typedEntries(obj);
* // Type: (["1", "one"] | ["foo", "bar"] | ["42", "answer"])[]
* ```
*
* @remarks
* - Runtime behavior is identical to Object.entries (all keys are strings)
* - Only TypeScript inference is enhanced to remember original key types
* - Works best with objects declared with 'as const' for literal type inference
* - Particularly useful for objects with mixed string and numeric keys
*
* @since 1.0.0
*/
export declare function typedEntries<T extends Record<any, unknown> = any>(obj: T): Array<{
[K in keyof T]: [K, T[K]];
}[keyof T]>;
export {};