@rzl-zone/utils-js
Version:
A modern, lightweight set of JavaScript utility functions for everyday development, crafted to enhance code readability and maintainability.
1,153 lines • 186 kB
TypeScript
import{FormatOptions}from 'date-fns';import{Locale}from 'date-fns/locale';type If<Condition,IfTrue=true,IfFalse=false>=Condition extends true ? IfTrue:IfFalse;type Not<T extends boolean>=T extends true ? false:true;type Extends<T,Base>=[T] extends [Base] ? true:false;type NotExtends<T,Base>=Not<Extends<T,Base>>;type IfExtends<T,Base,IfTrue=true,IfFalse=false>=If<Extends<T,Base>,IfTrue,IfFalse>;type IfNotExtends<T,Base,IfTrue=true,IfFalse=false>=If<NotExtends<T,Base>,IfTrue,IfFalse>;type IsAny<T>=0 extends 1 & T ? true:false;type PrettifyOptions={recursive:boolean;};type Prettify<T,Options extends PrettifyOptions={recursive:false;}>=T extends infer R ?{[K in keyof R]:If<Options["recursive"],Prettify<R[K],Options>,R[K]>;}:never;type OmitStrict<T,K extends keyof T,WithPrettify extends boolean=true,WithPrettifyRecursive extends boolean=true>=WithPrettify extends true ? Prettify<Omit<T,K>,{recursive:WithPrettifyRecursive;}>:WithPrettify extends false ? Omit<T,K>:never;type AnyFunction=(...args:any[])=>any;type TypedArray=Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array | BigInt64Array | BigUint64Array;type WebApiObjects=URL | URLSearchParams | FormData | Headers | Response | Request | ReadableStream<any>| WritableStream<any>| TransformStream<any,any>| MessageChannel | MessagePort | MessageEvent | Event | CustomEvent | HTMLElement | Node | Document | Window | AbortController | AbortSignal | TextEncoder | TextDecoder | CryptoKey | File | FileList | ImageBitmap | CanvasRenderingContext2D | WebSocket;type IntlObjects=Intl.Collator | Intl.DateTimeFormat | Intl.NumberFormat | Intl.RelativeTimeFormat | Intl.PluralRules | Intl.ListFormat | Intl.Locale;type NodeBuiltins=Buffer;type NonPlainObject=AnyFunction | Array<any>| Date | RegExp | Map<any,any>| Set<any>| WeakMap<any,any>| WeakSet<any>| Error | Promise<any>| ArrayBuffer | DataView | TypedArray | WebApiObjects | IntlObjects | NodeBuiltins | symbol |{[Symbol.toStringTag]:"Proxy";}| typeof Reflect;type Enumerate<N extends number,Acc extends number[]=[]>=Acc["length"] extends N ? Acc[number]:Enumerate<N,[...Acc,Acc["length"]]>;type RangeNumberTo999<From extends number,To extends number>=From extends To ? From:Exclude<Enumerate<To>,Enumerate<From>>extends never ? never:Exclude<Enumerate<To>,Enumerate<From>>| To;
/** -------------------------------------------------------
* * ***Asserts that a value is of type `string`.***
* -------------------------------------------------------
*
* Throws a `TypeError` if the value is not a string.
*
* @param {unknown} value - The value to check.
* @param {string | ((actualType: string) => string)} [message]
* Optional custom error message. If a function is provided,
* it receives the actual type (e.g. "number") and should return a string message.
* @returns {asserts value is string} Ensures `value` is `string` after this call.
*
* @throws {TypeError} If the value is not a string.
*
* @example
* assertIsString("hello"); // ✅ ok
*
* @example
* assertIsString(42); // ❌ throws TypeError: Expected value to be 'string', but got 'number'
*
* @example
* assertIsString(42, "Must be a string!"); // ❌ throws: Must be a string!
*
* @example
* assertIsString(42, (type) => `Expected string but got ${type}`); // ❌ throws: Expected string but got number
*/
declare const assertIsString:(value:unknown,message?:string |((typeValue:string)=>string))=>asserts value is string;
/** ---------------------------------------------
* * ***Converts all values in an array from numbers or other types to strings.***
* * ***The function can also remove invalid values (null, undefined) based on the options provided.***
* ---------------------------------
*
* * 🚫 Note: This function does NOT support recursive or nested arrays.
* It only processes a flat array of values.
*
* * Use `toStringDeep` if you want to recursive.
* ---------------------------------------------
*
* @param {Array<string | number | null | undefined>} [array] - The array to be transformed.
* @param {Object} [options] - The options object that controls the transformation behavior.
* @param {boolean} [options.removeInvalidValue=true] - If true, removes invalid values (null, undefined) from the result. Default is true.
* @returns {Array<string | null | undefined>} - A new array with string representations of the values or an array with invalid values removed if specified.
*
* @example
* toStringArrayUnRecursive([1, 2, '3'])
* // => ['1', '2', '3']
*
* @example
* toStringArrayUnRecursive([1, null, undefined, 'abc'], { removeInvalidValue: true })
* // => ['1', 'abc']
*
* @example
* toStringArrayUnRecursive([1, null, undefined, 'abc'], { removeInvalidValue: false })
* // => ['1', null, undefined, 'abc']
*
* @example
* toStringArrayUnRecursive(undefined)
* // => undefined
*/
declare function toStringArrayUnRecursive(array?:undefined | null,options?:{
/** If true, removes invalid values (null, undefined) from the result. Default is true.
* @default true
*/
removeInvalidValue:boolean;}):undefined;declare function toStringArrayUnRecursive(array?:Array<never>,options?:{
/** If true, removes invalid values (null, undefined) from the result. Default is true.
* @default true
*/
removeInvalidValue:boolean;}):Array<never>;declare function toStringArrayUnRecursive(array?:Array<undefined | null>| Array<null | undefined>,options?:{
/** If true, removes invalid values (null, undefined) from the result. Default is true.
* @default true
*/
removeInvalidValue:boolean;}):Array<undefined>;declare function toStringArrayUnRecursive<T>(array?:Array<T>,options?:{
/** If true, removes invalid values (null, undefined) from the result. Default is true.
* @default true
*/
removeInvalidValue:true;}):Array<string>| undefined;declare function toStringArrayUnRecursive<T>(array?:Array<T>,options?:{
/** If true, removes invalid values (null, undefined) from the result. Default is true.
* @default true
*/
removeInvalidValue:false;}):Array<string | null | undefined>| undefined;
/** ---------------------------------
* * ***Converts an array of string values (or values that can be cast to string) to an array of numbers.***
* * ***Optionally removes invalid values (non-numeric values) based on the provided options.***
* ---------------------------------
*
* * 🚫 Note: This function does NOT support recursive or nested arrays.
* It only processes a flat array of values.
*
* * Use `toNumbersDeep` if you want to recursive.
* ---------------------------------
*
* @param {Array<string | null | undefined>} [array] - The array of string values (or values convertible to strings) to be transformed into numbers.
* @param {Object} [options] - Options that affect the conversion behavior.
* @param {boolean} [options.removeInvalidValueNumber=true] - If true, removes invalid number values (e.g., NaN, undefined) from the result. Default is true.
* @returns {Array<number | undefined>} - An array of numbers converted from the string values, or an array with invalid values removed if specified.
*/
declare function toNumberArrayUnRecursive(array?:undefined | null,options?:{
/** If true, removes invalid number values (e.g., NaN, undefined) from the result. Default is true.
*
* @default true
*/
removeInvalidValueNumber?:boolean;}):undefined;declare function toNumberArrayUnRecursive(array?:Array<never>,options?:{
/** If true, removes invalid number values (e.g., NaN, undefined) from the result. Default is true.
*
* @default true
*/
removeInvalidValueNumber?:boolean;}):Array<never>;declare function toNumberArrayUnRecursive(array?:Array<undefined | null>| Array<null | undefined>,options?:{
/** If true, removes invalid number values (e.g., NaN, undefined) from the result. Default is true.
*
* @default true
*/
removeInvalidValueNumber?:boolean;}):Array<undefined>;declare function toNumberArrayUnRecursive<T>(array?:Array<T>,options?:{
/** If true, removes invalid number values (e.g., NaN, undefined) from the result. Default is true.
*
* @default true
*/
removeInvalidValueNumber?:true;}):Array<number>| undefined;declare function toNumberArrayUnRecursive<T>(array?:Array<T>,options?:{
/** If true, removes invalid number values (e.g., NaN, undefined) from the result. Default is true.
*
* @default true
*/
removeInvalidValueNumber:false;}):Array<number | undefined>| undefined;type ResUnFTN<Force extends false | "stringOrNumber" | "primitives" | "all"=false>=Force extends "all" ? Array<unknown[] | Record<string,unknown>| string>:Force extends "stringOrNumber" ? Array<string | boolean | bigint | symbol | null | undefined | Record<string,unknown>| AnyFunction | unknown[] | Date | RegExp | Map<unknown,unknown>| Set<unknown>| Promise<unknown>>:Force extends "primitives" ? Array<string | symbol | Record<string,unknown>| AnyFunction | unknown[] | Date | RegExp | Map<unknown,unknown>| Set<unknown>| Promise<unknown>>:Force extends false ? Array<string | number | bigint | boolean | symbol | RegExp | Record<string,unknown>| AnyFunction | Date | Map<unknown,unknown>| Set<unknown>| Promise<unknown>| unknown[] | null | undefined>:unknown[];type ResFTN<Force extends false | "stringOrNumber" | "primitives" | "all"=false>=Force extends "all" ? Array<string | Record<string,unknown>>:Force extends "stringOrNumber" ? Array<string | boolean | bigint | symbol | null | undefined | Record<string,unknown>| AnyFunction | Date | RegExp | Promise<unknown>>:Force extends "primitives" ? Array<string | symbol | RegExp | Record<string,unknown>| AnyFunction | Date | Promise<unknown>>:Force extends false ? Array<string | number | bigint | boolean | symbol | RegExp | Record<string,unknown>| AnyFunction | Date | Promise<unknown>| null | undefined>:unknown[];type DedupeResult<Force extends false | "stringOrNumber" | "primitives" | "all"=false,FTN extends boolean=false>=FTN extends false ? ResUnFTN<Force>:ResFTN<Force>;
/** ----------------------------------------------------------
* * ***Removes `null` and `undefined` values from an array, including nested arrays.***
* ----------------------------------------------------------
*
* - ✅ Returns `undefined` if the input is explicitly `undefined` or `null`.
* - ✅ Returns `[]` if input is empty or all elements are removed after filtering.
* - ✅ Recursively filters nested arrays while preserving structure.
* - ✅ Ensures proper type inference for safer downstream operations.
*
* @template T - The type of elements in the array.
* @param {T[]} [input] - The array to be filtered.
* @returns {T[] | undefined} A new array with `null` and `undefined` values removed,
* or `undefined` if the input is explicitly `undefined` or `null`.
*
* @example
* filterNullArray([1, null, 2, undefined, 3]);
* // => [1, 2, 3]
*
* @example
* filterNullArray([null, undefined]);
* // => []
*
* @example
* filterNullArray(undefined);
* // => undefined
* @example
* filterNullArray(null);
* // => undefined
*
* @example
* filterNullArray([]);
* // => []
*
* @example
* filterNullArray([1, [null, 2, [undefined, 3]]]);
* // => [1, [2, [3]]]
*/
declare const filterNullArray:<T>(input?:T[] | null)=>T[] | undefined;
/** ----------------------------------------------------------
* * ***Deduplicates values in an array (with optional flattening and deep stringification).***
* ----------------------------------------------------------
*
* Supports various modes for converting values to strings before deduplication:
* - `"stringOrNumber"`: Converts strings and numbers to strings.
* - `"primitives"`: Converts all primitives (string, number, boolean, bigint, null, undefined, NaN) to strings.
* - `"all"`: Converts all values (primitives, objects, Maps, Sets, Symbols, RegExp, Dates, Errors, Promises, functions)
* to strings, including nested object properties.
* - `false` (default): No conversion applied.
*
* Options:
* - `forceToString`: Enables string conversion for comparison, default is `false`.
* - `flatten`: If true, deeply flattens arrays, Maps, and Sets before deduplication, default is `false`.
*
* @template FTS - `forceToString` mode.
* @template FTN - `flatten` mode.
*
* @param {unknown[]} inputArray - The array to deduplicate. Can be deeply nested and contain any mix of types.
* @param {{ forceToString?: false | "stringOrNumber" | "primitives" | "all" }} [options] - Options to control string conversion.
* @returns {DedupeResult<FTS, FTN>} Deduplicated array with optional transformations.
*
* @throws {TypeError} If the input is not an array, or options is not an object, or if `forceToString` is invalid.
*
* @example
* dedupeArray(["apple", "banana", "apple"]);
* // => ["apple", "banana"]
*
* @example
* dedupeArray([[1, 2], [1, 2]], { flatten: true });
* // => [1, 2]
*
* @example
* dedupeArray([new Set([1, 2]), new Set([2, 3])], { flatten: true });
* // => [1, 2, 3]
*
* @example
* dedupeArray([1, "1", 2, "2"], { forceToString: "stringOrNumber" });
* // => ["1", "2"]
*
* @example
* dedupeArray([true, "true", false, undefined], { forceToString: "primitives" });
* // => ["true", "false", "undefined"]
*
* @example
* dedupeArray([1, "1", { a: 1 }], { forceToString: "all" });
* // => ["1", { a: "1" }]
*
* @example
* dedupeArray([1, 1, [2, 2, [3, 3]]]);
* // => [1, [2, [3]]]
*
* @example
* dedupeArray([null, undefined, null]);
* // => [null, undefined]
*
* @example
* dedupeArray([[], [[]], [[[]]], [[]], [[[]]]]);
* // => [[], [[]], [[[]]]]
*
* @example
* const fn = () => 1;
* dedupeArray([fn, fn, () => 1]);
* // => [fn, () => 1] cause: ref () => 1 and fn is different but ref const `fn` and `fn` is same ref.
*
* @example
* dedupeArray([Symbol("x"), Symbol("x")]);
* // => [Symbol("x")] (symbols are same by identity, so dedupe
*
* @example
* dedupeArray([NaN, NaN, 1, "1"]);
* // => [NaN, 1, "1"]
*
* @example
* dedupeArray([NaN, NaN, 1, "1"], { forceToString: "primitives" });
* // => ["NaN", "1"]
*
* @example
* dedupeArray([new Date("2025-01-01"), new Date("2025-01-01")]);
* // => [Date("2025-01-01")] (same time, deduped)
*
* @example
* dedupeArray([new Date("2025-01-01"), new Date("2025-01-01")], { forceToString: "all" });
* // => ["2025-01-01T00:00:00.000Z"]
*
* @example
* dedupeArray([/abc/, /abc/], { forceToString: "all" });
* // => ["/abc/"]
*
* @example
* dedupeArray([new Map(), new Set(), new Error("err")], { forceToString: "all" });
* // => ["[object Map]", "[object Set]", "Error: err"]
*
* @example
* dedupeArray([Promise.resolve(1), Promise.resolve(1)], { forceToString: "all" });
* // => ["[object Promise]"]
*
* @example
* dedupeArray([{ a: 1 }, { a: 1 }, { a: 2 }], { forceToString: "primitives" });
* // => [{ a: "1" }, { a: "2" }]
*
* @example
* dedupeArray([{ a: { b: 1 } }, { a: { b: 1 } }], { forceToString: "all" });
* // => [{ a: { b: "1" } }]
*
* @example
* dedupeArray("not an array");
* // Throws TypeError
*
* @example
* dedupeArray([1, 2, 3], { forceToString: "invalid" });
* // Throws TypeError
*/
declare const dedupeArray:<FTS extends false | "stringOrNumber" | "primitives" | "all"=false,FTN extends boolean=false>(inputArray:unknown[],options?:{
/** Enables string conversion for comparison, default is `false`.
*
* @default false
*/
forceToString?:FTS;
/** If true, deeply flattens arrays, Maps, and Sets before deduplication, default is `false`.
*
* @default false
*/
flatten?:FTN;})=>DedupeResult<FTS,FTN>;
/** ---------------------------------
* * ***Converts a given value into a boolean (strict).***
* ---------------------------------
*
* This is stricter than normal JS coercion:
* - `null` and `undefined` return `false`.
* - Empty strings return `false`, non-empty strings return `true`.
* - Numbers: `0` is `false`, others `true`.
* - Booleans returned as-is.
* - Arrays: `[]` is `false`, non-empty is `true`.
* - Objects: `{}` is `false`, object with keys is `true`.
*
* @param {unknown} [value] - The value to be converted.
* @returns {boolean} `true` if the value is considered non-empty, otherwise `false`.
*
* @example
* toBooleanContent(null); // false
* toBooleanContent(""); // false
* toBooleanContent(" "); // false
* toBooleanContent(" asd "); // true
* toBooleanContent("abc"); // true
* toBooleanContent(0); // false
* toBooleanContent(42); // true
* toBooleanContent([]); // false
* toBooleanContent([1]); // true
* toBooleanContent({}); // false
* toBooleanContent({ a: 1 }); // true
*/
declare const toBooleanContent:(value?:unknown)=>boolean;
/** -------------------------------------------------
* * ***Recursively checks if value is "non-empty".***
* -------------------------------------------------
*
* This function does a deep inspection to determine if the input
* contains any meaningful / non-empty value. It is stricter than
* JavaScript's normal truthy checks because it looks *inside*
* nested arrays & objects.
*
* Rules:
* - `null` and `undefined` return `false`
* - Empty strings `""` return `false`
* - `0` returns `false`
* - Empty arrays `[]` or empty objects `{}` return `false`
* - Checks deeply nested arrays/objects — if any value inside is "non-empty", returns `true`
*
* @param {unknown} [value] - The value to check.
* @returns {boolean} `true` if the value or anything nested inside is non-empty, otherwise `false`.
*
* @example
* toBooleanContentDeep(null); // false
* toBooleanContentDeep(""); // false
* toBooleanContentDeep(0); // false
* toBooleanContentDeep([]); // false
* toBooleanContentDeep({}); // false
* toBooleanContentDeep([[], {}]); // false
*
* toBooleanContentDeep("abc"); // true
* toBooleanContentDeep(42); // true
* toBooleanContentDeep([0, "", null]); // false
* toBooleanContentDeep([0, "", 5]); // true
* toBooleanContentDeep({ a: 0 }); // false
* toBooleanContentDeep({ a: 1 }); // true
* toBooleanContentDeep({ a: { b: [] }}); // false
* toBooleanContentDeep({ a: { b: "x" }}); // true
*/
declare const toBooleanContentDeep:(value?:unknown)=>boolean;
/** ---------------------------------
* * ***Converts a value into a strict boolean.***
* ---------------------------------
*
* This function checks if the input is a valid representation of `true`
* (e.g., `"true"`, `"on"`, `"yes"`, `"1"`, `1`, `true`, `"indeterminate"`).
* Any other value, including `undefined` and `null`, will return `false`.
*
* Supports optional `caseInsensitive` and `trimString` to customize string normalization.
*
* @param {unknown} [value] - The value to convert.
* @param {Object} [options] - Options for conversion behavior.
* @param {boolean} [options.caseInsensitive=false] - Whether string comparison ignores case. Default: `false`.
* @param {boolean} [options.trimString=true] - Whether to trim whitespace before comparison. Default: `true`.
* @returns {boolean} `true` if the value matches a truthy representation, otherwise `false`.
*
* @example
* toBooleanExplicit(true) // true
* toBooleanExplicit("on") // true
* toBooleanExplicit("Yes") // false
* toBooleanExplicit(" YES ", { trimString: false }) // false
* toBooleanExplicit(" YES ", { trimString: true, caseInsensitive: true }) // true
* toBooleanExplicit(" YES ", { trimString: true, caseInsensitive: false }) // false
* toBooleanExplicit("yes", { caseInsensitive: false }) // true
* toBooleanExplicit("1") // true
* toBooleanExplicit(1) // true
* toBooleanExplicit(0) // false
* toBooleanExplicit("off") // false
*/
declare const toBooleanExplicit:(value?:unknown,options?:{
/** Whether string comparison ignores case. Default: `false`.
*
* @default false
*/
caseInsensitive?:boolean;
/** Whether to trim whitespace before comparison. Default: `true`.
*
* @default true
*/
trimString?:boolean;})=>boolean;
/** ---------------------------------
* * ***Converts a given value into a boolean (loose).***
* ---------------------------------
*
* This follows JavaScript's typical truthy/falsy rules with some tweaks:
* - `null` and `undefined` return `false`.
* - Empty strings return `false`, non-empty strings return `true`.
* - Numbers: `0` is `false`, others `true`.
* - Booleans returned as-is.
* - Arrays: `[]` is `false`, non-empty is `true`.
* - Other objects: uses `Boolean(value)`, so `{}` is `true`.
*
* @param {unknown} [value] - The value to be converted.
* @returns {boolean} `true` if the value is truthy, otherwise `false`.
*
* @example
* toBooleanLoose(null); // false
* toBooleanLoose(""); // false
* toBooleanLoose("abc"); // true
* toBooleanLoose(0); // false
* toBooleanLoose(42); // true
* toBooleanLoose([]); // false
* toBooleanLoose([1]); // true
* toBooleanLoose({}); // true
* toBooleanLoose({ a: 1 }); // true
*/
declare const toBooleanLoose:(value?:unknown)=>boolean;
/** * ----------------------------------------------------------
* * ***Extracts digits from a string or number input.***
* ----------------------------------------------------------
*
* ✅ Converts the input to a string, trims whitespace, and removes any characters
* that are not digits (`0-9`).
*
* ✅ Returns the cleaned numeric value as a `number`.
*
* 🚩 If the input is `null`, `undefined`, or results in no digits,
* it safely returns `0`.
*
* @param {string | number | null | undefined} value
* The value to process. Accepts a string, number, `null`, or `undefined`.
*
* @returns {number}
* The numeric value after extracting digits.
* Returns `0` if input is invalid or contains no digits.
*
* @example
* extractDigits("123abc456"); // ➔ 123456
* extractDigits("$1,234.56"); // ➔ 123456
* extractDigits("9A8B7C6"); // ➔ 9876
* extractDigits("abc"); // ➔ 0
* extractDigits(undefined); // ➔ 0
* extractDigits(null); // ➔ 0
* extractDigits(12345); // ➔ 12345
* extractDigits(" 00a "); // ➔ 0
*/
declare const extractDigits:(value?:string | number | null)=>number;
/** -------------------------------------------------------------
* * Parses a human-friendly currency string into a JavaScript number.
* -------------------------------------------------------------
*
* 🚀 Supports multi-locale formats:
*
* - European: "15.000,10" ➔ 15300.10
* - US: "15,000.10" ➔ 15300.10
* - Swiss: "15'000.10" ➔ 15300.10
* - French: "15 000,10" ➔ 15300.10
* - Indian: "1,23,456.78" ➔ 123456.78
* - Compact: "15300000,10" ➔ 15300000.10
*
* ✅ Features:
* - Strips symbols automatically: "Rp", "$", "EUR", etc.
* - Handles bracket negatives: "(15.000,10)" ➔ -15300.10
* - Normalizes decimal separator (last dot or comma).
* - Detects non-breaking spaces (\u00A0, \u202F) often in European data.
* - Fallback to 0 for empty, invalid, or non-numeric strings.
*
* 🔍 How it parses internally:
* 1. Removes all characters except digits, ., ,, ', spaces.
* 2. Detects bracket (...) as negative.
* 3. If Indian style (1,23,456) detected by multiple ,\d{2}, removes all commas.
* 4. Otherwise:
* - If multiple dots & no commas ➔ thousands: removes all .
* - If multiple commas & no dots ➔ thousands: removes all ,
* - If mixed, treats last , or . as decimal
* 5. Converts final decimal to . for JS float.
*
* 🛠 Gotchas:
* - If both . and , are present, last occurrence is used as decimal.
* - For strings like "1.121.234,56" ➔ decimal is ,.
* - For "1,121,234.56" ➔ decimal is ..
* - For "15300000,2121" ➔ decimal becomes . internally.
*
* @param {string} input
* Any messy currency string. May contain:
* - currency symbols (Rp, $, CHF, EUR)
* - thousands separators (.,', space, \u00A0, \u202F)
* - various decimal formats (, or .)
* - bracket negative: "(15.000,10)"
*
* @returns {number}
* JavaScript float representation.
* Will return 0 for invalid, empty, or non-string input.
*
* 📦 Examples of input ➔ output:
* @example
* parseCurrencyString("Rp 15.300.000,21");
* // ➔ 15300000.21
*
* parseCurrencyString("15 300 000,21");
* // ➔ 15300000.21
*
* parseCurrencyString("CHF 15'300'000.21");
* // ➔ 15300000.21
*
* parseCurrencyString("$15,300,000.21");
* // ➔ 15300000.21
*
* parseCurrencyString("(15.000,10)");
* // ➔ -15000.10
*
* parseCurrencyString("1,23,456.78");
* // ➔ 123456.78
*
* parseCurrencyString("15300000,2121");
* // ➔ 15300000.2121
*
* parseCurrencyString("USD 15 300 000.21");
* // ➔ 15300000.21
*
* parseCurrencyString("");
* // ➔ 0
*
* parseCurrencyString("abc");
* // ➔ 0
*
* @description
* * Notes:
* - Use this function as a first step to **sanitize currency inputs**
* before storing into database or doing math.
* - Always pair this with your formatter for consistent output display.
*/
declare const parseCurrencyString:(input?:string | null)=>number;
/** ----------------------------------------------------------
* * ***Converts a value from a string to its natural JavaScript type.***
* ----------------------------------------------------------
*
* ✅ Supported conversions:
* - `"true"` → `true`
* - `"false"` → `false`
* - `"null"` → `null`
* - `"undefined"` → `undefined`
* - `"42"` → `42` (number)
* - `"3.14"` → `3.14` (number)
* - `"3,567,890.14"` → `3567890.14` (number)
* - `" "` → `""` (trimmed)
* - Other strings are returned trimmed & lowercased.
* - Non-string inputs are returned unchanged.
*
* @example
* convertType("true") // → true
* convertType(" 42 ") // → 42
* convertType("FALSE") // → false
* convertType(" null ") // → null
* convertType(" ") // → ""
* convertType(100) // → 100
* convertType({}) // → {}
*
* @param {any} value - The value to convert (usually string or unknown type).
* @returns {any} The converted JavaScript type (boolean, number, null, undefined, or original).
*/
declare const convertType:(value:unknown)=>unknown;type NonJsonParsableType=Omit<Exclude<unknown,string | null | undefined>,string>;type Contains<T,U>=[Extract<T,U>] extends [never] ? false:true;type UnknownValue={undefined:true;};type SafeJsonParseResult<TData,T>=IfNotExtends<T,NonJsonParsableType>extends true ? T extends never ? undefined:T extends void ? undefined:T extends number ? undefined:Contains<T,string>extends true ? Contains<T,null & string>extends true ? TData | null | undefined:TData | undefined:IfExtends<T,null>extends true ? null:IfNotExtends<T,NonJsonParsableType>extends true ? TData | null | undefined:undefined:Contains<T,string>extends true ? IsAny<T>extends true ? TData | undefined | null:TData | undefined:undefined;interface CleanParsedDataOptions{
/** Convert numeric strings to numbers (e.g., `"42"` → `42`).
*
* @default false
*/
convertNumbers?:boolean;
/** Convert `"true"` / `"false"` strings to boolean values.
*
* @default false
*/
convertBooleans?:boolean;
/** Convert valid date strings into `Date` objects.
*
* @default false
*/
convertDates?:boolean;
/** Custom date formats to be parsed (e.g., `["DD/MM/YYYY", "MM/DD/YYYY"]`).
*
* @default []
*/
customDateFormats?:string[];
/** Remove `null` values from objects and arrays.
*
* @default false
*/
removeNulls?:boolean;
/**
* Remove `undefined` values from objects and arrays.
*
* - `false` (default): replaces `undefined` with `null`
* - `true`: removes keys with `undefined` values
*/
removeUndefined?:boolean;
/** Remove empty objects `{}` from the final output.
*
* @default false
*/
removeEmptyObjects?:boolean;
/** Remove empty arrays `[]` from the final output.
*
* @default false
*/
removeEmptyArrays?:boolean;
/** Strict mode: Removes values that do not match selected conversions.
*
* @default false
*/
strictMode?:boolean;
/** Enable error logging if JSON parsing fails.
*
* @default false
*/
loggingOnFail?:boolean;
/** Custom error handler function.
*
* @default undefined
*/
onError?:(error:unknown)=>void;}
/** --------------------------------------------------
* * ***Cleans parsed JSON data based on provided options.***
* --------------------------------------------------
*
* @template T - Expected output type.
* @param {unknown} data - The parsed JSON data.
* @param {CleanParsedDataOptions} options - Cleaning options.
* @returns {T | undefined} - The cleaned data.
*
* **Note: If using `convertDates`, result may contain Date objects. You may need type assertions in strict TypeScript settings.**
*
* @example
* // Convert numbers and remove nulls
* const result = cleanParsedData({ age: "25", name: null }, { convertNumbers: true, removeNulls: true });
* console.log(result); // Output: { age: 25 }
*
* @example
* // Convert boolean strings
* const result = cleanParsedData({ isActive: "true" }, { convertBooleans: true });
* console.log(result); // Output: { isActive: true }
*/
declare const cleanParsedData:<T=unknown>(data:T,options?:CleanParsedDataOptions)=>T | undefined | null;
/** --------------------------------------------------
* * ***Parses custom date formats like "DD/MM/YYYY" or "MM/DD/YYYY".***
* --------------------------------------------------
*
* @param {string} dateString - Date string to parse.
* @param {string} format - Date format to match.
* @returns {Date | null} - Returns a Date object if valid, otherwise null.
*/
declare const parseCustomDate:(dateString:string,format:string)=>Date | null;
/** --------------------------------------------------
* * ***Safely parses JSON while handling errors and applying transformations.***
* --------------------------------------------------
*
* - ✅ **Supports generics** to ensure accurate return type inference.
* - Always provide both `<TData, TInput>` for best results.
* - ***Scroll down for full generic behavior explanation.***
* - ✅ Automatically parses valid JSON strings into objects, arrays, numbers, etc.
* - ✅ Supports data transformation via options (e.g., convert strings to numbers, booleans, or dates).
* - ✅ Returns:
* 1. `null` → if input is explicitly `null`.
* 2. `undefined` → if input is `undefined`, not a string, or if parsing fails.
* 3. Parsed and cleaned result (`TData`) → if input is a valid JSON string.
*
* ⚠ **JSON.stringify note**: If the input JSON string was created using `JSON.stringify()`, any properties with
* `undefined` values would have been automatically removed or converted to `null` depending on the serializer.
* Example:
* ```ts
* JSON.stringify({ a: undefined, b: 1 }); // → '{"b":1}'
* JSON.parse('{"a": undefined, "b": 1}') // ❌ invalid JSON
*
* safeJsonParse('{"name": "John", "score": undefined}');
* // result → { name:"John", score:null } ← because `undefined` is not valid JSON, gets replaced
* ```
* Therefore, if you see `undefined` in raw input, it will likely throw unless pre-cleaned or replaced with `null`.
* @template TData - The expected output type after parsing and cleaning.
* @template TInput - The input value type, used for advanced type inference and return typing.
*
* @param {TInput} value - The JSON string or value to parse.
* @param {CleanParsedDataOptions} [options] - Options to clean, convert types, enable strict mode,
* support custom date formats, enable logging, or handle errors via callback.
*
* @returns {SafeJsonParseResult<TData, TInput>} Parsed and optionally cleaned result, or `null`/`undefined`.
*
* @throws {TypeError} If `options` is provided but not a valid object.
*
* @example
* 1. ***Basic parse with number & boolean conversion:***
* ```ts
* const result = safeJsonParse('{"age": "30", "isActive": "true"}', {
* convertNumbers: true,
* convertBooleans: true
* });
* // result → { age: 30, isActive: true }
* ```
* 2. ***Handling `undefined` in input string (manually written, not JSON.stringify):***
* ```ts
* const result = safeJsonParse('{"score": undefined}');
* // result → { score: null } ← because `undefined` is not valid JSON, gets replaced
* ```
*
* 3. ***Strict mode (removes invalid values):***
* ```ts
* const result = safeJsonParse('{"name": " ", "score": "99abc"}', {
* convertNumbers: true,
* strictMode: true
* });
* // result → {}
*
* const result2 = safeJsonParse('{"name": " ", "score": undefined}');
* // result2 → { name:"",score: null }
* ```
*
* 4. ***Custom date format parsing:***
* ```ts
* const result = safeJsonParse('{"birthday": "25/12/2000"}', {
* convertDates: true,
* customDateFormats: ["DD/MM/YYYY"]
* });
* // result → { birthday: new Date("2000-12-25T00:00:00.000Z") }
* ```
*
* 5. ***Invalid JSON with custom error handling:***
* ```ts
* safeJsonParse("{invalid}", {
* loggingOnFail: true,
* onError: (err) => console.log("Custom handler:", err.message)
* });
* // → Logs parsing error and invokes handler
* ```
*
* 6. ***Null or non-string input returns null/undefined:***
* ```ts
* safeJsonParse(null); // → null
* safeJsonParse(undefined); // → undefined
* safeJsonParse(123); // → undefined
* ```
*
* 7. ***Generic usage: Provide both output and input type to ensure correct return typing:***
* ```ts
* type UserType = { name: string };
*
* const obj = JSON.stringify({
* name: "John"
* });
*
* const toParse = isAuth() ? obj : null;
* const toParse2 = isAuth() ? obj : undefined;
*
* // * `Without Generic`:
* const parsed = safeJsonParse(toParse);
* //- runtime: { name: "John" } | undefined | null
* //- type: Record<string, unknown> | undefined | null
* const parsed2 = safeJsonParse(toParse);
* //- runtime: { name: "John" } | undefined
* //- type: Record<string, unknown> | undefined
*
* // * `With Generic`:
* const parsed = safeJsonParse<UserType>(toParse);
* //- runtime: { name: "John" } | undefined | null
* //- type: undefined ← (⚠ unexpected!)
* const parsed2 = safeJsonParse<UserType>(toParse);
* //- runtime: { name: "John" } | undefined
* //- type: undefined ← (⚠ unexpected!)
* const parsed = safeJsonParse<UserType, typeof toParse>(toParse);
* //- runtime: { name: "John" } | null | undefined
* //- type: UserType | null | undefined
* const parsed2 = safeJsonParse<UserType, typeof toParse>(toParse);
* //- runtime: { name: "John" } | undefined
* //- type: UserType | undefined
* ```
* @note
* ⚠ **Generic Behavior:**
* - This function supports advanced generic inference for clean, type-safe return values.
* - If only the first generic (`TData`) is provided and the second (`TInput`) is omitted,
* then `TInput` defaults to `undefined`, resulting in a return type of `undefined`.
* - To ensure correct return typing, **always pass both generics** when `value` is dynamic,
* nullable, or unioned: `safeJsonParse<TData, typeof value>(value)`.
* - This makes the returned type exactly match your expectation: `TData | null | undefined`.
*/
declare function safeJsonParse<TData extends Record<string,any>=Record<string,unknown>,TInput extends UnknownValue=UnknownValue>(value:TInput,options?:CleanParsedDataOptions):IsAny<TInput>extends true ? TData | null | undefined:undefined;declare function safeJsonParse<TData extends Record<string,any>=Record<string,unknown>,TInput extends string | null | undefined | unknown=undefined>(value:TInput,options?:CleanParsedDataOptions):SafeJsonParseResult<TData,TInput>;type Prev=[never,RangeNumberTo999<1,40>];type DotPath<T,Prefix extends string="",Depth extends number=RangeNumberTo999<1,40>>=Depth extends never ? never:T extends(infer U)[] ? U extends object ? DotPath<U,`${Prefix}`,Prev[Depth]>:never:T extends object ?{[K in Extract<keyof T,string>]:T[K] extends object ? DotPath<T[K],`${Prefix}${K}.`,Prev[Depth]>| `${Prefix}${K}`:`${Prefix}${K}`;}[Extract<keyof T,string>]:never;type ConfigRemoveObjectPaths<T>={key:DotPath<T>;deep?:boolean;};
/** ------------------------------------------------------------------------
* * ***Deletes multiple keys (shallow or deeply nested) from an object.***
* ------------------------------------------------------------------------
*
* ✅ Features:
* - Removes one or more keys from an object based on their paths (supports dot notation for nested).
* - Can delete deeply from all matching nested levels (even inside arrays) when `deep: true`.
* - By default does **not mutate** the original object. Clones it first.
* Set `deepClone = false` to mutate in place (useful for performance on large data).
* - Ensures type safety on `key` paths via `DotPath<T>`, reducing accidental invalid paths.
*
* 🔍 Behavior:
* - When `deep: false` (default), only deletes the direct property at the specified path.
* - When `deep: true`, searches deeply and recursively deletes the key from all levels,
* including inside arrays of objects (applies the *same* path repeatedly).
* - Can delete nested properties safely without throwing even if intermediate objects are missing.
*
* 🚀 Edge Handling:
* - Ignores invalid intermediate objects (will just skip that branch).
* - If `object` is `null` or not an object, returns an empty object.
* - Throws if `keysToDelete` is not a proper array of `{ key, deep? }` objects.
*
* @template T - The shape of the input object, used for type-safe dot paths.
*
* @param {T} object - The object to remove keys from. Must be an object or will return `{}`.
* @param {Array<{ key: DotPath<T>, deep?: boolean }>} keysToDelete -
* An array of instructions:
* - `key`: A string path using dot notation (e.g. `"user.profile.name"`).
* - `deep`: If `true`, will recursively remove all instances of the key path at any depth.
* @param {boolean} [deepClone=true] -
* Whether to deep clone the original object before modifying.
* - `true` (default): returns a *new object* with the specified keys removed.
* - `false`: modifies the original object in place and returns it.
*
* @returns {Partial<T>}
* - A new object with specified keys removed if `deepClone` is `true`.
* - The *same mutated object* if `deepClone` is `false`.
*
* @throws {TypeError}
* - If `object` is not an object.
* - If `keysToDelete` is not an array of `{ key, deep? }` objects.
*
* @example
* // 🟢 Shallow deletion
* removeObjectPaths(
* { a: 1, b: 2, c: { d: 3 } },
* [{ key: "b" }]
* );
* // => { a: 1, c: { d: 3 } }
*
* @example
* // 🟢 Nested deletion (shallow, removes only exact path)
* removeObjectPaths(
* { user: { profile: { name: "Alice", age: 30 } } },
* [{ key: "user.profile.age" }]
* );
* // => { user: { profile: { name: "Alice" } } }
*
* @example
* // 🔥 Deep deletion (recursively removes key from all levels and arrays)
* removeObjectPaths(
* { items: [{ price: 10 }, { price: 20, details: { price: 30 } }] },
* [{ key: "price", deep: true }]
* );
* // => { items: [{}, { details: {} }] }
*
* @example
* // 📝 Without cloning: mutates original object
* const obj = { x: 1, y: 2 };
* removeObjectPaths(obj, [{ key: "y" }], false);
* console.log(obj); // => { x: 1 }
*
* @example
* // 🚫 Invalid usage throws
* removeObjectPaths(42, [{ key: "a" }]);
* // => throws TypeError
*/
declare const removeObjectPaths:<T extends Record<string,unknown>>(object:T,keysToDelete:ConfigRemoveObjectPaths<T>[],deepClone?:boolean)=>Partial<T>;
/** --------------------------------------------
* * ***Safely converts a JavaScript value into a stable, JSON-compatible string.***
* --------------------------------------------
*
* Features:
* - Recursively sorts object keys if `sortKeys` is true, to ensure stable key order.
* - Optionally sorts array values if `ignoreOrder` is true (only sorts shallow primitives inside arrays).
* - Removes functions and symbols (they are omitted from the output).
* - Converts `undefined`, `NaN`, `Infinity`, `-Infinity` to `null`.
* - Converts `BigInt` to a string (since JSON does not support it).
* - Handles circular references by replacing them with the string `"[Circular]"`.
* - Serializes:
* - `Date` instances as ISO strings.
* - `Map` as `{ map: [ [key, value], ... ] }`.
* - `Set` as `{ set: [values...] }`.
*
* Compared to `JSON.stringify`, this ensures **stable output**:
* - Same object structure always produces the same string.
* - Useful for deep equality checks, hashing, caching keys, or snapshot tests.
*
* @param {unknown} value
* The value to serialize. Can be primitives, objects, arrays, Maps, Sets, Dates, etc.
*
* @param {boolean} [sortKeys=true]
* Whether to sort object keys alphabetically (recursively). If `false`, preserves original insertion order.
*
* @param {boolean} [ignoreOrder=false]
* Whether to sort array primitive values. When `true`:
* - Only primitive values in arrays are sorted.
* - Objects and nested arrays keep their position and are placed after sorted primitives.
* If `false`, arrays retain their original order.
*
* @param {boolean} [pretty=false]
* If `true`, output is formatted with 2-space indentation and newlines (pretty-printed).
* If `false`, produces compact single-line JSON.
*
* @returns {string}
* A stable JSON string representation of the input value.
*
* @throws {TypeError}
* Throws if `sortKeys`, `ignoreOrder`, or `pretty` are not strictly boolean.
*
* @example
* // Basic object key sorting
* safeStableStringify({ b: 2, a: 1 });
* // => '{"a":1,"b":2}'
*
* @example
* // Disable key sorting (preserve insertion order)
* safeStableStringify({ b: 2, a: 1 }, false);
* // => '{"b":2,"a":1}'
*
* @example
* // Sorting arrays
* safeStableStringify([3, 1, 2], true, true);
* // => '[1,2,3]'
*
* @example
* // Nested object + ignoreOrder=true
* safeStableStringify({ z: [3, 1, 2], x: { d: 4, c: 3 } }, true, true);
* // => '{"x":{"c":3,"d":4},"z":[1,2,3]}'
*
* @example
* // sortKeys=false and ignoreOrder=true
* safeStableStringify({ z: [3, 1, 2], x: { d: 4, c: 3 } }, false, true);
* // => '{"z":[1,2,3],"x":{"d":4,"c":3}}'
*
* @example
* // pretty print output
* safeStableStringify([3, 1, 2], true, true, true);
* // => `[
* // 1,
* // 2,
* // 3
* // ]`
*
* @example
* // Handles Date, BigInt, Map and Set
* safeStableStringify({
* time: new Date("2025-01-01"),
* big: BigInt(9007199254740991),
* data: new Map([["key", new Set([1, 2])]])
* });
* // => '{"big":"9007199254740991","data":{"map":[["key",{"set":[1,2]}]]},"time":"2025-01-01T00:00:00.000Z"}'
*
* @example
* // Functions and symbols are removed
* safeStableStringify({ f: () => {}, s: Symbol("wow") });
* // => '{}'
*
* @example
* // undefined, NaN, Infinity convert to null
* safeStableStringify([undefined, NaN, Infinity, -Infinity]);
* // => '[null,null,null,null]'
*
* @example
* // Circular reference
* const obj = { name: "A" };
* obj.self = obj;
* safeStableStringify(obj);
* // => '{"name":"A","self":"[Circular]"}'
*
* @example
* // Complex nested ignoreOrder with objects
* const arr = [9, 7, [4, 2, 3], { z: [5, 1, 6] }];
* safeStableStringify(arr, true, true);
* // => '[7,9,[2,3,4],{"z":[1,5,6]}]'
*/
declare const safeStableStringify:(value:unknown,sortKeys?:boolean,ignoreOrder?:boolean,pretty?:boolean)=>string;
/** ----------------------------------------------------------
* * ***Recursively converts a value into a string based on the `forceToString` option.***
* ----------------------------------------------------------
*
* - `"stringOrNumber"`: Converts strings and numbers to strings.
* - `"primitives"`: Converts all primitives (number, string, boolean, bigint, undefined, null, NaN) to strings.
* - `"all"`: Converts everything, including symbols, functions, Dates, RegExp, Maps, Sets, Errors, Promises,
* and deeply all object properties, to strings.
* - `false` (default): Leaves everything unchanged.
*
* Special behaviors:
* - `NaN` → `"NaN"` only in `"primitives"` or `"all"` mode.
* - `Date` → ISO string only in `"all"` mode.
* - `RegExp` → Source string (e.g. `/abc/i`) only in `"all"` mode.
* - `Symbol` → `Symbol(description)` string only in `"all"` mode.
* - `Map` → Array of [key, value] pairs with keys/values stringified deeply (only in `"all"` mode).
* - `Set` → Array of values stringified deeply (only in `"all"` mode).
* - `Function` → Source code string (e.g. `"() => 1"`) only in `"all"` mode.
* - `Error`, `Promise` → Stringified via `.toString()` only in `"all"` mode.
*
*
* @param {unknown} value - The value to process. Can be anything: primitive, array, object, function, etc.
* @param {false | "stringOrNumber" | "primitives" | "all"} forceToString - The mode of string conversion.
* @returns {unknown} A new value with the conversion applied based on `forceToString`.
*
* @example
* toStringDeepForce(42, "stringOrNumber");
* // => "42"
*
* @example
* toStringDeepForce(true, "primitives");
* // => "true"
*
* @example
* toStringDeepForce(null, "primitives");
* // => "null"
*
* @example
* toStringDeepForce(Symbol("x"), "all");
* // => "Symbol(x)"
*
* @example
* toStringDeepForce({ a: 1, b: [2, NaN] }, "primitives");
* // => { a: "1", b: ["2", "NaN"] }
*
* @example
* toStringDeepForce(new Date("2025-01-01"), "all");
* // => "2025-01-01T00:00:00.000Z"
*
* @example
* toStringDeepForce(() => 1, "all");
* // => "() => 1"
*
* @example
* toStringDeepForce(/abc/i, "all");
* // => "/abc/i"
*
* @example
* toStringDeepForce(new Map([["a", 1], ["b", 2]]), "all");
* // => [["a", "1"], ["b", "2"]]
*
* @example
* toStringDeepForce(new Set([1, 2, 3]), "all");
* // => ["1", "2", "3"]
*
* @example
* toStringDeepForce(new Error("Oops"), "all");
* // => "Error: Oops"
*
* @example
* toStringDeepForce(Promise.resolve(1), "all");
* // => "[object Promise]"
*
* @example
* toStringDeepForce({ func: () => 123 }, "all");
* // => { func: "() => 123" }
*
* @example
* toStringDeepForce([1, "a", { b: 2 }], false);
* // => [1, "a", { b: 2 }]
*/
declare const toStringDeepForce:(value:unknown,forceToString:false | "stringOrNumber" | "primitives" | "all")=>unknown;type ConvertedDeepNumber<T,RemoveEmptyObjects extends boolean,RemoveEmptyArrays extends boolean>=T extends null | undefined ? never:T extends number | `${number}` ? number:T extends any[] ? ConvertedDeepNumber<T[number],RemoveEmptyObjects,RemoveEmptyArrays>[]:T extends Record<string,unknown>?{[K in keyof T]:ConvertedDeepNumber<T[K],RemoveEmptyObjects,RemoveEmptyArrays>;}extends infer O ? RemoveEmptyObjects extends true ? keyof O extends never ? never:O:O:never:never;
/** --------------------------------------------------
* * ***Converts deeply nested arrays or objects into number while preserving structure.***
* --------------------------------------------------
*
* Features:
* - ✅ Removes `null`, `undefined`, NaN, Infinity, and non-numeric values.
* - 🔄 Recursively processes nested objects and arrays.
* - 🔢 Converts valid number, including decimals (e.g. `"3.5"` → `3.5`).
* - 🧹 Can remove empty objects `{}` or arrays `[]` based on flags.
*
* @template T - The input data type (Array, Object, etc)
* @template RemoveEmptyObjects - Whether to remove empty objects
* @template RemoveEmptyArrays - Whether to remove empty arrays
*
* @param {T} input - The data to convert
* @param {boolean} [removeEmptyObjects=false] - Remove empty objects `{}` if `true`
* @param {boolean} [removeEmptyArrays=false] - Remove empty arrays `[]` if `true`
*
* @returns {ConvertedDeepNumber<T, RemoveEmptyObjects, RemoveEmptyArrays> | undefined}
* The transformed data, or `undefined` if entirely empty after processing.
*
* @example
* toNumberDeep("123") // → 123
* toNumberDeep("12.34") // → 12.34
* toNumberDeep("not number") // → undefined
*
* @example
* toNumberDeep([NaN, Infinity, -Infinity, "10"])
* // → [10]
*
* @example
* toNumberDeep({ a: {}, b: [] }, false, false)
* // → { a: {}, b: [] }
*
* @example
* toNumberDeep({ a: {}, b: [] }, true, false)
* // → { b: [] }
*
* @example
* toNumberDeep({ a: {}, b: [] }, false, true)
* // → { a: {} }
*
* @example
* toNumberDeep({ a: {}, b: [], c: { d: null } }, true, true)
* // → {}
*
* @example
* toNumberDeep({
* a: "1",
* b: {
* c: "not num",
* d: ["2", "3.5", null, { e: "4.4", f: "invalid" }],
* },
* g: [],
* })
* // → { a: 1, b: { d: [2, 3.5, { e: 4.4 }] }, g: [] }
*
* @example
* toNumberDeep({ x: {}, y: [], z: [{ a: {}, b: [] }] }, false, true)
* // → { x: {}, z: [{ a: {} }] }
*
* @example
* toNumberDeep({ x: {}, y: [], z: [{ a: {}, b: [] }] }, true, false)
* // → { y: [], z: [{ b: [] }] }
*
* @example
* toNumberDeep({
* x: {},
* y: [],
* z: [{ a: {}, b: [], c: "3" }, { d: "4.5" }]
* }, true, true)
* // → { z: [{ c: 3 }, { d: 4.5 }] }
*
* @example
* toNumberDeep([[[[[["1"]]], null]], "2", "abc"], false, true)
* // → [[[[[[1]]]]], 2]
*
* @example
* toNumberDeep(["1", {}, [], ["2", {}, []]], true, true)
* // → [1, [2]]
*
* @example
* toNumberDeep(["1", () => {}, Symbol("wow"), "2"])
* // → [1, 2]
*
* @example
* toNumberDeep({ a: { b: {} } }, false, true)
* // → { a: { b: {} } }
*
* @example
* toNumberDeep(["1", { a: {} }], true)
* // → [1]
*
* @example
* toNumberDeep(["1", { a: {} }], false)
* // → [1, { a: {} }]
*
* @example
* toNumberDeep(["1", [], { a: [] }], false, false)
* // → [1, [], { a: [] }]
*/
declare const toNumberDeep:<T extends unknown,RemoveEmptyObject