UNPKG

@ayonli/jsext

Version:

A JavaScript extension package for building strong and modern applications.

311 lines (310 loc) 10.5 kB
/** * Functions for dealing with objects. * @module */ import { Constructor } from "./types.ts"; /** * Returns `true` if the specified object has the indicated property as its own property. * If the property is inherited, or does not exist, the function returns `false`. * * @example * ```ts * import { hasOwn } from "@ayonli/jsext/object"; * * const obj = { foo: "hello" }; * * console.log(hasOwn(obj, "foo")); // true * console.log(hasOwn(obj, "toString")); // false * ``` */ export declare function hasOwn(obj: any, key: string | number | symbol): boolean; /** * Returns `true` if the specified object has the indicated method as its own method (in its own * prototype). If the method is inherited, or is not in the prototype, or does not exist, this * function returns `false`. * * @example * ```ts * import { hasOwnMethod } from "@ayonli/jsext/object"; * * class MyClass { * foo() { * return "Hello"; * } * * bar = () => "World"; * } * * const obj = new MyClass(); * * console.log(hasOwnMethod(obj, "foo")); // true * console.log(hasOwnMethod(obj, "bar")); // false * console.log(hasOwnMethod(obj, "toString")); // false * ``` */ export declare function hasOwnMethod(obj: any, method: string | symbol): boolean; /** * Copies the key-value pairs that are presented in the source objects but are missing in * the target object into the target, later pairs are skipped if the same key already exists. * * This function mutates the target object and returns it. * * @example * ```ts * import { patch } from "@ayonli/jsext/object"; * * const obj1 = { foo: "Hello" }; * const obj2 = { foo: "Hi", bar: "World" }; * * console.log(patch(obj1, obj2)); // { foo: "Hello", bar: "World" } * ``` */ export declare function patch<T extends {}, U>(target: T, source: U): T & U; export declare function patch<T extends {}, U, V>(target: T, source1: U, source2: V): T & U & V; export declare function patch<T extends {}, U, V, W>(target: T, source1: U, source2: V, source3: W): T & U & V & W; export declare function patch(target: object, ...sources: any[]): any; /** * Creates an object composed of the picked keys. * * @example * ```ts * import { pick } from "@ayonli/jsext/object"; * * const obj = { foo: "Hello", bar: "World" }; * * console.log(pick(obj, ["foo"])); // { foo: "Hello" } * ``` */ export declare function pick<T extends object, U extends keyof T>(obj: T, keys: U[]): Pick<T, U>; export declare function pick<T>(obj: T, keys: (string | symbol)[]): Partial<T>; /** * Creates an object composed without the picked keys. * * **NOTE:** * This function only collect keys from the object's own properties, except for type Error, * whose `name`, `message` and `cause` are always collected. * * @example * ```ts * import { omit } from "@ayonli/jsext/object"; * * const obj = { foo: "Hello", bar: "World" }; * * console.log(omit(obj, ["foo"])); // { bar: "World" } * ``` */ export declare function omit<T extends object, U extends keyof T>(obj: T, keys: U[]): Omit<T, U>; export declare function omit<T>(obj: T, keys: (string | symbol)[]): Partial<T>; /** * Checks if the value is an instance of the given type, returns the value itself if passed, * otherwise returns `null`. This function is mainly used for the optional chaining syntax. * * @example * ```ts * import { as } from "@ayonli/jsext/object"; * * try { * // ... do something * } catch (err) { * console.error(as(err, Error)?.message ?? String(err)); * } * ``` */ export declare function as(value: unknown, type: StringConstructor): string | null; export declare function as(value: unknown, type: NumberConstructor): number | null; export declare function as(value: unknown, type: BigIntConstructor): bigint | null; export declare function as(value: unknown, type: BooleanConstructor): boolean | null; export declare function as(value: unknown, type: SymbolConstructor): symbol | null; export declare function as<T>(value: unknown, type: Constructor<T>): T | null; export type TypeNames = "string" | "number" | "bigint" | "boolean" | "symbol" | "function" | "class" | "undefined" | "null"; /** * Returns a string representation or the constructor of the value's type. * * **NOTE:** This function returns `"class"` for ES6 classes. * * **NOTE:** This function returns `"null"` for `null`. * * **NOTE:** This function returns `Object` for `Object.create(null)`. * * @example * ```ts * import { typeOf } from "@ayonli/jsext/object"; * * console.log(typeOf("Hello")); // string * console.log(typeOf(42)); // number * console.log(typeOf(42n)); // bigint * console.log(typeOf(true)); // boolean * console.log(typeOf(Symbol("foo"))); // symbol * console.log(typeOf(() => {})); // function * console.log(typeOf(class Foo {})); // class * console.log(typeOf(undefined)); // undefined * console.log(typeOf(null)); // null * console.log(typeOf({ foo: "bar" })); // [Function: Object] * console.log(typeOf(Object.create(null))); // [Function: Object] * console.log(typeOf([1, 2, 3])); // [Function: Array] * console.log(typeOf(new Date())); // [Function: Date] * ``` */ export declare function typeOf<T>(value: T): TypeNames | Constructor<T>; /** * Returns `true` if the given value is valid. The following values are considered invalid: * * - `undefined` * - `null` * - `NaN` * - `Invalid Date` */ export declare function isValid(value: unknown): boolean; /** * Returns `true` is the given value is a plain object, that is, an object created by * the `Object` constructor or one with a `[[Prototype]]` of `null`. * * @example * ```ts * import { isPlainObject } from "@ayonli/jsext/object"; * * console.log(isPlainObject({ foo: "bar" })); // true * console.log(isPlainObject(Object.create(null))); // true * console.log(isPlainObject(new Map([["foo", "bar"]]))); // false * ``` */ export declare function isPlainObject(value: unknown): value is { [x: string | symbol]: any; }; /** * Creates an object base on the original object but without any invalid values * (except for `null`), and trims the value if it's a string. * * **NOTE:** This function only operates on plain objects and arrays. * * @example * ```ts * import { sanitize } from "@ayonli/jsext/object"; * * const obj = sanitize({ * foo: "Hello", * bar: " World ", * baz: undefined, * num: NaN, * }); * * console.log(obj); // { foo: "Hello", bar: "World" } * ``` */ export declare function sanitize<T extends object>(obj: T, deep?: boolean, options?: { removeNulls?: boolean; removeEmptyStrings?: boolean; removeEmptyObjects?: boolean; removeArrayItems?: boolean; }): T; /** * Creates an object with sorted keys (in ascending order) of the original object. * * **NOTE:** Symbol keys are not sorted and remain their original order. * * **NOTE:** This function only operates on plain objects and arrays. * * @example * ```ts * import { sortKeys } from "@ayonli/jsext/object"; * * const obj = sortKeys({ foo: "Hello", bar: "World" }); * * console.log(JSON.stringify(obj)); // { "bar": "World", "foo": "Hello" } * ``` */ export declare function sortKeys<T extends object>(obj: T, deep?: boolean): T; export type OmitChildrenNodes<T extends object> = Pick<T, { [K in keyof T]: T[K] extends any[] ? K : T[K] extends object ? never : K; }[keyof T]>; /** * Create an object with flatted keys of the original object, the children * nodes' properties will be transformed to a string-represented path. * * **NOTE:** This function only operates on plain objects and arrays. * * @param depth Default value: `1`. * @example * ```ts * import { flatKeys } from "@ayonli/jsext/object"; * * const obj = flatKeys({ foo: { bar: "Hello", baz: "World" } }); * * console.log(obj); // { "foo.bar": "Hello", "foo.baz": "World" } * ``` */ export declare function flatKeys<T extends object>(obj: T, depth?: number, options?: { flatArrayIndices?: boolean; }): OmitChildrenNodes<T> & Record<string | number | symbol, any>; /** * Returns a new record with all entries of the given record except the ones * that do not match the given predicate. * * This function is effectively as * `Object.fromEntries(Object.entries(obj).filter(predicate))`. * * @example * ```ts * import { filterEntries } from "@ayonli/jsext/object"; * * const obj = { foo: "Hello", bar: "World" }; * const result = filterEntries(obj, ([key]) => key === "foo"); * * console.log(result); // { foo: "Hello" } * ``` */ export declare function filterEntries<T>(obj: Record<string, T>, predicate: (entry: [string, T]) => boolean): Record<string, T>; /** * Applies the given transformer to all entries in the given record and returns * a new record containing the results. * * This function is effectively as * `Object.fromEntries(Object.entries(obj).map(transformer))`. * * @example * ```ts * import { mapEntries } from "@ayonli/jsext/object"; * * const obj = { foo: "Hello", bar: "World" }; * const result = mapEntries(obj, ([key, value]) => [key, value.toUpperCase()]); * * console.log(result); // { foo: "HELLO", bar: "WORLD" } * ``` */ export declare function mapEntries<T, O>(obj: Record<string, T>, transformer: (entry: [string, T]) => [string, O]): Record<string, O>; /** * Returns a tuple of two records with the first one containing all entries of * the given record that match the given predicate and the second one containing * all that do not. * * @example * ```ts * import { partitionEntries } from "@ayonli/jsext/object"; * * const obj = { foo: "Hello", bar: "World" }; * const [match, rest] = partitionEntries(obj, ([key]) => key === "foo"); * * console.log(match); // { foo: "Hello" } * console.log(rest); // { bar: "World" } * ``` */ export declare function partitionEntries<T>(record: Record<string, T>, predicate: (entry: [string, T]) => boolean): [Record<string, T>, Record<string, T>]; /** * Composes a new record with all keys and values inverted. * * This function is effectively as * `Object.fromEntries(Object.entries(record).map(([key, value]) => [value, key]))`. * * @example * ```ts * import { invert } from "@ayonli/jsext/object"; * * const obj = { foo: "Hello", bar: "World" }; * const result = invert(obj); * * console.log(result); // { Hello: "foo", World: "bar" } * ``` */ export declare function invert<T extends Record<PropertyKey, PropertyKey>>(record: Readonly<T>): { [P in keyof T as T[P]]: P; };