A comprehensive JavaScript utility library for working with native objects that extends Array, Date, Function, Number, Object, RegExp, and String with powerful methods.
—
The Sugar Object module provides comprehensive utilities for object manipulation, querying, filtering, and type checking. It extends JavaScript's native Object capabilities with over 80 methods for working with objects in a functional programming style.
import Sugar from "sugar";
// Methods available as Sugar.Object.methodName()For CommonJS:
const Sugar = require("sugar");
// Methods available as Sugar.Object.methodName()Creates objects from various input formats.
/**
* Creates an object from a query string with parsing options
* @param str - Query string to parse
* @param options - Parsing configuration options
* @returns Parsed object
*/
function fromQueryString<T,U>(
str: string,
options?: QueryStringParseOptions<T,U>
): any;
interface QueryStringParseOptions<T,U> {
deep?: boolean;
separator?: string;
transform?: (key: string, value: any) => any;
}Usage Examples:
import Sugar from "sugar";
// Basic query string parsing
const params = Sugar.Object.fromQueryString("name=John&age=30&active=true");
// Result: { name: "John", age: "30", active: "true" }
// With custom separator
const data = Sugar.Object.fromQueryString("name:John;age:30", { separator: ";" });
// With transformation
const typed = Sugar.Object.fromQueryString("age=30&score=95.5", {
transform: (key, value) => {
if (key === "age" || key === "score") {
return parseFloat(value);
}
return value;
}
});Methods for adding, merging, cloning, and modifying objects.
/**
* Adds properties from source object to target
* @param instance - Target object to modify
* @param obj - Source object to add from
* @param options - Merge options
* @returns Modified target object
*/
function add<T>(
instance: T,
obj: any,
options?: ObjectMergeOptions<T>
): T;
/**
* Adds properties from multiple source objects
* @param instance - Target object to modify
* @param sources - Array of source objects
* @param options - Merge options
* @returns Modified target object
*/
function addAll<T>(
instance: T,
sources: any[],
options?: ObjectMergeOptions<T>
): T;
/**
* Creates a copy of the object (shallow or deep)
* @param instance - Object to clone
* @param deep - Whether to perform deep cloning
* @returns Cloned object
*/
function clone(instance: any, deep?: boolean): any;
/**
* Sets default values for undefined properties
* @param instance - Target object
* @param sources - Default values object or array
* @param options - Merge options
* @returns Object with defaults applied
*/
function defaults<T>(
instance: T,
sources: any,
options?: ObjectMergeOptions<T>
): T;
/**
* Merges source object into target object
* @param instance - Target object
* @param source - Source object to merge
* @param options - Merge options
* @returns Merged object
*/
function merge<T>(
instance: T,
source: any,
options?: ObjectMergeOptions<T>
): T;
/**
* Merges multiple source objects into target
* @param instance - Target object
* @param sources - Array of source objects
* @param options - Merge options
* @returns Merged object
*/
function mergeAll<T>(
instance: T,
sources: any[],
options?: ObjectMergeOptions<T>
): T;
/**
* Sets a property value on the object
* @param instance - Target object
* @param key - Property key to set
* @param val - Value to set
* @returns Modified object
*/
function set<T>(instance: T, key: string, val: any): T;
/**
* Executes a function with the object and returns the object
* @param instance - Object to tap
* @param tapFn - Function to execute with object
* @returns Original object (for chaining)
*/
function tap(instance: any, tapFn: Function): any;
interface ObjectMergeOptions<T> {
deep?: boolean;
descriptor?: boolean;
hidden?: boolean;
resolve?: boolean;
}Usage Examples:
import Sugar from "sugar";
// Adding properties
const user = { name: "John" };
Sugar.Object.add(user, { age: 30, city: "NYC" });
// Result: { name: "John", age: 30, city: "NYC" }
// Deep cloning
const original = { user: { name: "John", scores: [1, 2, 3] } };
const copy = Sugar.Object.clone(original, true);
// Setting defaults
const config = { port: 3000 };
Sugar.Object.defaults(config, { host: "localhost", ssl: false });
// Result: { port: 3000, host: "localhost", ssl: false }
// Tapping for side effects
const result = Sugar.Object.tap(user, (obj) => console.log("Processing:", obj.name));Methods for accessing and inspecting object properties.
/**
* Gets a property value from the object
* @param instance - Object to query
* @param key - Property key to get
* @param inherited - Whether to include inherited properties
* @returns Property value
*/
function get<T>(instance: any, key: string, inherited?: boolean): T;
/**
* Tests if object has a specific property
* @param instance - Object to test
* @param key - Property key to check
* @param inherited - Whether to include inherited properties
* @returns True if property exists
*/
function has(instance: any, key: string, inherited?: boolean): boolean;
/**
* Returns an array of the object's property keys
* @param instance - Object to get keys from
* @returns Array of property keys
*/
function keys<T>(instance: T): string[];
/**
* Returns an array of the object's property values
* @param instance - Object to get values from
* @returns Array of property values
*/
function values<T>(instance: T): any[];
/**
* Returns the number of properties in the object
* @param instance - Object to count properties
* @returns Number of properties
*/
function size(instance: any): number;
/**
* Tests if the object is empty (has no enumerable properties)
* @param instance - Object to test
* @returns True if object is empty
*/
function isEmpty(instance: any): boolean;Usage Examples:
import Sugar from "sugar";
const user = { name: "John", age: 30, city: "NYC" };
// Getting values
const name = Sugar.Object.get(user, "name"); // "John"
const missing = Sugar.Object.get(user, "email", false); // undefined
// Checking existence
const hasAge = Sugar.Object.has(user, "age"); // true
const hasEmail = Sugar.Object.has(user, "email"); // false
// Getting keys and values
const userKeys = Sugar.Object.keys(user); // ["name", "age", "city"]
const userValues = Sugar.Object.values(user); // ["John", 30, "NYC"]
// Size and emptiness
const count = Sugar.Object.size(user); // 3
const empty = Sugar.Object.isEmpty({}); // trueMethods for selecting, excluding, and filtering object properties.
/**
* Excludes properties that match the search criteria
* @param instance - Object to filter
* @param search - Criteria to exclude by
* @returns Object with excluded properties removed
*/
function exclude<T>(instance: T, search: any): T;
/**
* Filters properties that match the search criteria
* @param instance - Object to filter
* @param search - Criteria to filter by
* @returns Object with matching properties only
*/
function filter<T>(instance: T, search: any): T;
/**
* Rejects properties that match the pattern
* @param instance - Object to process
* @param find - Pattern to reject
* @returns Object with rejected properties removed
*/
function reject(instance: any, find: any): any;
/**
* Removes properties that match the search criteria
* @param instance - Object to modify
* @param search - Criteria for removal
* @returns Modified object
*/
function remove<T>(instance: T, search: any): T;
/**
* Selects properties that match the pattern
* @param instance - Object to process
* @param find - Pattern to select
* @returns Object with selected properties only
*/
function select(instance: any, find: any): any;Usage Examples:
import Sugar from "sugar";
const user = {
name: "John",
age: 30,
password: "secret",
email: "john@example.com"
};
// Filtering by function
const publicData = Sugar.Object.filter(user, (key, value) => key !== "password");
// Result: { name: "John", age: 30, email: "john@example.com" }
// Excluding specific keys
const withoutAge = Sugar.Object.exclude(user, ["age", "password"]);
// Result: { name: "John", email: "john@example.com" }
// Selecting with regex
const emailFields = Sugar.Object.select(user, /email/);
// Result: { email: "john@example.com" }Methods for performing set-like operations on objects.
/**
* Returns properties that exist in both objects
* @param instance - First object
* @param obj - Second object to intersect with
* @returns Object containing common properties
*/
function intersect(instance: any, obj: any): any;
/**
* Removes properties that exist in the second object
* @param instance - Object to subtract from
* @param obj - Object containing properties to remove
* @returns Object with subtracted properties removed
*/
function subtract(instance: any, obj: any): any;
/**
* Inverts the key-value pairs of the object
* @param instance - Object to invert
* @param multi - Whether to handle multiple keys with same value
* @returns Object with inverted key-value pairs
*/
function invert(instance: any, multi?: boolean): any;Usage Examples:
import Sugar from "sugar";
const obj1 = { a: 1, b: 2, c: 3 };
const obj2 = { b: 2, c: 4, d: 5 };
// Intersection (common properties)
const common = Sugar.Object.intersect(obj1, obj2);
// Result: { b: 2 }
// Subtraction
const diff = Sugar.Object.subtract(obj1, obj2);
// Result: { a: 1 }
// Inversion
const lookup = Sugar.Object.invert({ name: "John", city: "NYC" });
// Result: { "John": "name", "NYC": "city" }Methods for iterating over and testing object properties.
/**
* Tests if all properties match the search criteria
* @param instance - Object to test
* @param search - Criteria to test against
* @returns True if all properties match
*/
function every<T>(instance: T, search: any): boolean;
/**
* Finds the first property that matches the search criteria
* @param instance - Object to search
* @param search - Criteria to search for
* @returns First matching property value
*/
function find<T>(instance: T, search: any): any;
/**
* Iterates over object properties with a callback function
* @param instance - Object to iterate
* @param eachFn - Function to call for each property
* @returns Original object
*/
function forEach<T>(instance: T, eachFn: Function): T;
/**
* Tests if no properties match the search criteria
* @param instance - Object to test
* @param search - Criteria to test against
* @returns True if no properties match
*/
function none<T>(instance: T, search: any): boolean;
/**
* Tests if some properties match the search criteria
* @param instance - Object to test
* @param search - Criteria to test against
* @returns True if any properties match
*/
function some<T>(instance: T, search: any): boolean;
/**
* Counts properties that match the search criteria
* @param instance - Object to count in
* @param search - Criteria to count
* @returns Number of matching properties
*/
function count<T>(instance: T, search: any): number;
/**
* Reduces object properties to a single value
* @param instance - Object to reduce
* @param reduceFn - Reducer function
* @param init - Initial value
* @returns Reduced value
*/
function reduce<T>(instance: T, reduceFn: Function, init?: any): any;Usage Examples:
import Sugar from "sugar";
const scores = { math: 95, science: 87, english: 92, history: 78 };
// Testing all properties
const allPassing = Sugar.Object.every(scores, (key, value) => value >= 70); // true
// Finding first match
const firstHigh = Sugar.Object.find(scores, (key, value) => value >= 90); // 95
// Iterating with side effects
Sugar.Object.forEach(scores, (key, value) => {
console.log(`${key}: ${value}`);
});
// Counting matches
const highScores = Sugar.Object.count(scores, (key, value) => value >= 90); // 2
// Reducing to total
const total = Sugar.Object.reduce(scores, (sum, key, value) => sum + value, 0); // 352Methods for calculating statistics on object values.
/**
* Calculates the average of object values
* @param instance - Object to average
* @param map - Optional mapping function
* @returns Average value
*/
function average<T,U>(instance: T, map?: Function): number;
/**
* Finds the minimum values in the object
* @param instance - Object to search
* @param all - Whether to return all minimum values
* @param map - Optional mapping function
* @returns Minimum value(s)
*/
function least<T,U>(instance: T, all?: boolean, map?: Function): any;
/**
* Finds the maximum values in the object
* @param instance - Object to search
* @param all - Whether to return all maximum values
* @param map - Optional mapping function
* @returns Maximum value(s)
*/
function max<T,U>(instance: T, all?: boolean, map?: Function): any;
/**
* Calculates the median of object values
* @param instance - Object to calculate median for
* @param map - Optional mapping function
* @returns Median value
*/
function median<T,U>(instance: T, map?: Function): number;
/**
* Finds the minimum values in the object
* @param instance - Object to search
* @param all - Whether to return all minimum values
* @param map - Optional mapping function
* @returns Minimum value(s)
*/
function min<T,U>(instance: T, all?: boolean, map?: Function): any;
/**
* Finds the maximum values in the object
* @param instance - Object to search
* @param all - Whether to return all maximum values
* @param map - Optional mapping function
* @returns Maximum value(s)
*/
function most<T,U>(instance: T, all?: boolean, map?: Function): any;
/**
* Calculates the sum of object values
* @param instance - Object to sum
* @param map - Optional mapping function
* @returns Sum of values
*/
function sum<T,U>(instance: T, map?: Function): number;Usage Examples:
import Sugar from "sugar";
const prices = { laptop: 999, mouse: 29, keyboard: 79, monitor: 299 };
// Statistical calculations
const avgPrice = Sugar.Object.average(prices); // 351.5
const total = Sugar.Object.sum(prices); // 1406
const cheapest = Sugar.Object.min(prices); // 29
const mostExpensive = Sugar.Object.max(prices); // 999
const medianPrice = Sugar.Object.median(prices); // 189
// With mapping function
const lengths = { short: "hi", medium: "hello", long: "hello world" };
const avgLength = Sugar.Object.average(lengths, (key, value) => value.length); // 6.33Methods for checking the type and nature of values.
/**
* Tests if value is an arguments object
* @param instance - Value to test
* @returns True if value is arguments object
*/
function isArguments(instance: any): boolean;
/**
* Tests if value is an array
* @param instance - Value to test
* @returns True if value is array
*/
function isArray(instance: any): instance is any[];
/**
* Tests if value is a boolean
* @param instance - Value to test
* @returns True if value is boolean
*/
function isBoolean(instance: any): instance is boolean;
/**
* Tests if value is a Date object
* @param instance - Value to test
* @returns True if value is Date
*/
function isDate(instance: any): instance is Date;
/**
* Tests if value is empty (null, undefined, empty string/array/object)
* @param instance - Value to test
* @returns True if value is empty
*/
function isEmpty(instance: any): boolean;
/**
* Tests deep equality between two values
* @param instance - First value
* @param other - Second value to compare
* @returns True if values are deeply equal
*/
function isEqual(instance: any, other: any): boolean;
/**
* Tests if value is an Error object
* @param instance - Value to test
* @returns True if value is Error
*/
function isError(instance: any): instance is Error;
/**
* Tests if value is a function
* @param instance - Value to test
* @returns True if value is function
*/
function isFunction(instance: any): instance is Function;
/**
* Tests if value is a Map object
* @param instance - Value to test
* @returns True if value is Map
*/
function isMap(instance: any): instance is Map<any, any>;
/**
* Tests if value is a number
* @param instance - Value to test
* @returns True if value is number
*/
function isNumber(instance: any): instance is number;
/**
* Tests if value is an object (but not null or array)
* @param instance - Value to test
* @returns True if value is object
*/
function isObject(instance: any): instance is object;
/**
* Tests if value is a RegExp object
* @param instance - Value to test
* @returns True if value is RegExp
*/
function isRegExp(instance: any): instance is RegExp;
/**
* Tests if value is a Set object
* @param instance - Value to test
* @returns True if value is Set
*/
function isSet(instance: any): instance is Set<any>;
/**
* Tests if value is a string
* @param instance - Value to test
* @returns True if value is string
*/
function isString(instance: any): instance is string;Usage Examples:
import Sugar from "sugar";
// Type checking
const data = { items: [1, 2, 3], name: "test", count: 42 };
Sugar.Object.isArray(data.items); // true
Sugar.Object.isObject(data); // true
Sugar.Object.isString(data.name); // true
Sugar.Object.isNumber(data.count); // true
Sugar.Object.isDate(new Date()); // true
// Emptiness testing
Sugar.Object.isEmpty([]); // true
Sugar.Object.isEmpty({}); // true
Sugar.Object.isEmpty(""); // true
Sugar.Object.isEmpty(null); // true
Sugar.Object.isEmpty({ a: 1 }); // false
// Deep equality
const obj1 = { a: [1, 2], b: { c: 3 } };
const obj2 = { a: [1, 2], b: { c: 3 } };
Sugar.Object.isEqual(obj1, obj2); // true
// Function testing
Sugar.Object.isFunction(() => {}); // true
Sugar.Object.isFunction(console.log); // trueMethods for converting objects to and from serialized formats.
/**
* Converts object to query string format
* @param instance - Object to serialize
* @param options - Serialization options
* @returns Query string representation
*/
function toQueryString<T,U>(
instance: T,
options?: QueryStringOptions<T,U>
): string;
interface QueryStringOptions<T,U> {
deep?: boolean;
prefix?: string;
separator?: string;
transform?: (key: string, value: any) => any;
}Usage Examples:
import Sugar from "sugar";
// Basic serialization
const params = { name: "John", age: 30, active: true };
const query = Sugar.Object.toQueryString(params);
// Result: "name=John&age=30&active=true"
// With custom separator and prefix
const custom = Sugar.Object.toQueryString(params, {
separator: ";",
prefix: "user"
});
// With transformation
const encoded = Sugar.Object.toQueryString(params, {
transform: (key, value) => {
if (typeof value === "boolean") {
return value ? "1" : "0";
}
return value;
}
});
// Result: "name=John&age=30&active=1"
// Deep serialization for nested objects
const nested = { user: { name: "John", prefs: { theme: "dark" } } };
const deep = Sugar.Object.toQueryString(nested, { deep: true });interface ObjectMergeOptions<T> {
/** Whether to perform deep merging of nested objects */
deep?: boolean;
/** Whether to copy property descriptors */
descriptor?: boolean;
/** Whether to include non-enumerable properties */
hidden?: boolean;
/** Whether to resolve conflicts using a resolution function */
resolve?: boolean;
}
interface QueryStringParseOptions<T,U> {
/** Whether to parse nested objects from dot notation */
deep?: boolean;
/** Custom separator for key-value pairs */
separator?: string;
/** Function to transform parsed values */
transform?: (key: string, value: any) => any;
}
interface QueryStringOptions<T,U> {
/** Whether to serialize nested objects using dot notation */
deep?: boolean;
/** Prefix to add to all parameter names */
prefix?: string;
/** Custom separator for key-value pairs */
separator?: string;
/** Function to transform values before serialization */
transform?: (key: string, value: any) => any;
}