npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@niche-works/utils

v0.4.2

Published

`@niche-works/utils` is a niche library of general-purpose utility functions covering a wide range of categories including arrays, objects, strings, numbers, dates, timers, and more.

Readme

@niche-works/utils

@niche-works/utils is a niche library of general-purpose utility functions covering a wide range of categories including arrays, objects, strings, numbers, dates, timers, and more.

日本語の README はこちら

Installation

npm install @niche-works/utils
# or
pnpm add @niche-works/utils

Usage

import { ensureArray, normalizeString, rangeClamp } from '@niche-works/utils';

You can also import by category.

import { ensureArray } from '@niche-works/utils/array';
import { normalizeString } from '@niche-works/utils/string';

Data Last Pattern

Many functions have a .dataLast property that returns a curried function receiving data as the last argument. This is useful for pipeline processing.

import { ensureArray } from '@niche-works/utils/array';

// data-first (normal call)
const arr = ensureArray('hello'); // ['hello']

// data-last (curried)
const toArray = ensureArray.dataLast();
const arr2 = toArray('hello'); // ['hello']

API Reference

array — Array Operations

asArray(data, options?) *

Converts any value to an array. Iterables are spread; strings and primitives become single-element arrays.

asArray([1, 2, 3]); // [1, 2, 3]
asArray('hello'); // ['hello']
asArray(null); // []
asArray(new Set([1, 2])); // [1, 2]

| Option | Type | Description | | ------ | --------- | ----------------------------------------------------------------- | | raw | boolean | When true, wraps iterables as a single element without spreading |


ensureArray(data, options?) *

Wraps a non-array value in an array. Returns an empty array for null/undefined.

ensureArray([1, 2]); // [1, 2]
ensureArray(42); // [42]
ensureArray(null); // []

| Option | Type | Description | | ------ | --------- | ------------------------------------------------------------------------ | | raw | boolean | When true, wraps the value as a single element without checking if it's an array |


cycle(data, size) *

Generates a new array of the specified size by cycling (looping) through the input array. A negative size reverses the direction.

cycle([1, 2, 3], 7); // [1, 2, 3, 1, 2, 3, 1]
cycle([1, 2, 3], -5); // [3, 2, 1, 3, 2]

insertAt(data, index, items, options?) *

Inserts elements at the specified index. The index is clamped to the valid range.

insertAt([1, 2, 3], 1, [10, 20]); // [1, 10, 20, 2, 3]

| Option | Type | Description | | --------- | --------- | ---------------------------------------------- | | inplace | boolean | When true, directly modifies the original array |


pushAll(data, source, options?) *

Returns a new array with all elements of source appended to data. Returns null if data is null.

pushAll([1, 2], [3, 4]); // [1, 2, 3, 4]

pushAllMutable(data, source) *

Mutably appends all elements of another array to the array.

const arr = [1, 2];
pushAllMutable(arr, [3, 4]); // arr => [1, 2, 3, 4]

pushUnique(data, items, options?) *

Returns a new array with only non-duplicate elements from items appended.

pushUnique([1, 2], [2, 3, 4]); // [1, 2, 3, 4]

pushUniqueMutable(data, items, options?) *

Mutably appends only non-duplicate elements from items to the array.


rotateArray(data, options?) *

Rotates the array by taking elements from the front and adding them to the end.

rotateArray([1, 2, 3, 4, 5], { count: 2 }); // [3, 4, 5, 1, 2]

| Option | Type | Description | | --------- | --------- | ------------------------------------------------- | | count | number | Number of elements to rotate (default: 1) | | inplace | boolean | When true, directly modifies the original array |


nestedKeyBy(data, properties, options?) *

Converts an array into a nested object keyed by property values. Each leaf holds a single item.

const users = [
  { id: 'a', role: 'admin', name: 'Alice' },
  { id: 'b', role: 'user', name: 'Bob' },
];
nestedKeyBy(users, ['role', 'id']);
// { admin: { a: {...} }, user: { b: {...} } }

| Option | Type | Description | | -------------- | --------- | ----------------------------------------------------------------------------- | | overwrite | boolean | When true, later values take precedence for duplicate keys (default: earlier values take precedence) | | flat | boolean | When true, produces a flat object with concatenated keys | | keySeparator | string | Key separator for flat mode (default: '.') |


nestedGroupBy(data, properties, options?) *

Converts an array into a nested object keyed by property values. Each leaf holds an array of items.

nestedGroupBy(users, 'role');
// { admin: [...], user: [...] }

sortDependencies(data, options?) *

Topologically sorts an array based on dependencies. Throws if circular dependencies are detected.

const nodes = [
  { id: 'A', deps: ['B'] },
  { id: 'B', deps: [] },
];
sortDependencies(nodes, {
  idProp: 'id',
  depsProp: 'deps',
  depsIdProp: (dep) => dep,
  ignoreNoSubstance: true,
});
// [{ id: 'B' }, { id: 'A' }]

| Option | Type | Description | | ------------------- | --------------------- | --------------------------------------------------------- | | idProp | keyof I \| Function | Property name or function to get the ID | | depsProp | keyof I \| Function | Property name or function to get the dependency list | | depsIdProp | keyof I \| Function | Property name or function to get the dependency item's ID | | isTree | boolean | Process tree-structured dependencies | | ignoreNoSubstance | boolean | Ignore non-existent dependency targets | | desc | boolean | When true, reverses the order |


swapPairs(data) *

Swaps elements in adjacent pairs within the array.

swapPairs([1, 2, 3, 4]); // [2, 1, 4, 3]

maybeFind(data, predicate) *

Returns the first element matching the predicate, or undefined if none is found.


maybeMap(data, mapper, options?) *

Maps each element and returns a new array with null/undefined values removed.


firstDefined(data) *

Returns the first non-undefined value in the array.


firstPresent(data) *

Returns the first non-null/non-undefined value in the array.


clearArray(data)

Removes all elements from the array (mutating).


boolean — Boolean

ensureBoolean(value, options?) *

Converts a value to a boolean. Strings like 'true', '1', and 'yes' can also be converted to true.

ensureBoolean('true'); // true
ensureBoolean(0); // false
ensureBoolean('yes', { trueValues: ['yes'] }); // true

compare — Comparison

compare(left, operator, right) *

Compares two values using an operator and returns a boolean.

compare(5, '>', 3); // true
compare(5, 'between', [1, 10]); // true
compare('a', 'in', ['a', 'b']); // true

Supported operators: '=' '!=' '<' '<=' '>' '>=' 'between' 'in' 'notIn'


isEqualBy(a, b, options?) *

Checks equality of two values using the specified comparison mode.

isEqualBy({ a: 1 }, { a: 1 }, { mode: 'deep' }); // true

| Option | Type | Description | | ------------ | ------------------------------- | ------------------------------------ | | mode | 'strict' \| 'loose' \| 'deep' | Comparison mode (default: 'strict') | | customizer | Function | Custom comparison function |


isEqualWith(a, b, customizer) *

Recursively checks equality of two values using a custom comparator function.


date — Date

asUtcDate(date)

Returns a new Date that interprets the local date's year/month/day/hour/minute/second components as UTC values.

// JST 2024-01-15 12:00:00 → treated as UTC 2024-01-15 12:00:00
asUtcDate(new Date(2024, 0, 15, 12, 0, 0));

createUtcDate(year, month, day, ...)

Creates a date in the UTC timezone.


interpolateDate(value, ratio, options?) *

Returns a date interpolated between two dates at the given ratio.

interpolateDate(targetDate, 0.5, { baseValue: startDate });
// date halfway between startDate and targetDate

format — Format

analyzeNumberFormat(format)

Parses a number format string (e.g. Excel format) and returns information about integer/decimal digit counts, separators, prefix/suffix, etc.

analyzeNumberFormat('#,##0.00');
// { intNumLength: 1, dp: true, dpLength: 2, ... }

function — Function Utilities

withCache(fn, options?)

Caches the result of an async function to prevent duplicate requests with the same arguments.

const cachedFetch = withCache(fetchUser, { ttl: 60000 });
await cachedFetch('user-1'); // API call
await cachedFetch('user-1'); // returned from cache

| Option | Type | Description | | ---------- | ---------- | ------------------------------ | | ttl | number | Cache time-to-live (ms) | | cacheKey | Function | Cache key generator function |


withRetry(fn, maxRetries, options?)

An async function wrapper that automatically retries on failure.

const reliableFetch = withRetry(fetchData, 3, {
  delay: 1000,
  exponentialBackoff: true,
});

| Option | Type | Description | | -------------------- | ---------- | -------------------------------------- | | delay | number | Wait time before retry (ms) | | exponentialBackoff | boolean | Use exponential backoff | | shouldRetry | Function | Function to determine whether to retry | | onRetry | Function | Callback called on retry |


withTimeout(fn, timeout, options?)

An async function wrapper that throws TimeoutError if it doesn't complete within the specified time.

const timedFetch = withTimeout(fetchData, 5000);

withFallback(fn, fallback, options?)

An async function wrapper that returns a fallback value when an error occurs.

const safeFetch = withFallback(fetchData, null);

alwaysTrue() / alwaysFalse() / alwaysInput(v) / alwaysVoid()

Functions that always return a fixed value.

alwaysTrue(); // true
alwaysFalse(); // false
alwaysInput('hi'); // 'hi'
alwaysVoid(); // undefined

maybeApply(fn, value)

Applies the function only if value is not null/undefined.


maybeCall(fn, ...args)

Calls fn only if it is a function.


ensureAsync(fn)

Converts a synchronous function into an asynchronous one (returns a Promise).


geometry — Geometry

fitToRatio(value, ratio, options?) *

Scales a value to fit an aspect ratio.

fitToRatio(100, 16 / 9, { mode: 'expand' }); // 178
fitToRatio(100, 16 / 9, { mode: 'shrink' }); // 56

| Option | Type | Description | | ---------- | ---------------------- | -------------------- | | mode | 'expand' \| 'shrink' | Expand or shrink mode | | decimals | number | Decimal places |

Dedicated functions for specific ratios are also provided.

| Function | Ratio | Data Last | | --------------- | ------------------- | --------- | | fitToGolden | Golden ratio (1.618…) | ✓ | | fitToSilver | Silver ratio (2.414…) | | | fitToBronze | Bronze ratio (3.303…) | | | fitToDouble | 2:1 | | | fitToYamato | Yamato ratio (√2) | | | fitToSqrt2 | √2 | | | fitToSqrt3 | √3 | | | fitToSqrt5 | √5 | | | fitToHarmonic | Harmonic ratio | | | fitToPlatinum | Platinum ratio | |


input — Input Control

limitDecimal(value, options?)

Validates and formats numeric input. Supports decimal place limits, min/max constraints, and both interactive (typing in progress) and batch processing modes.

limitDecimal('3.14159', { dp: 2 }); // '3.14'
limitDecimal('999', { max: 100 }); // '100'
limitDecimal('-', { interactive: true, min: -100 }); // '-' (allow while typing)

| Option | Type | Description | | ------------- | ------------------ | ----------------------------------------------------- | | dp | number | Maximum decimal places | | min | number \| string | Minimum value | | max | number \| string | Maximum value | | interactive | boolean | Allow in-progress states (-, trailing ., etc.) |


limitNaturalNumber(value, options?)

Converts and limits values to natural numbers (positive integers).

limitNaturalNumber(3.7); // 3
limitNaturalNumber(0); // null (zero not allowed)
limitNaturalNumber(0, { allowZero: true }); // 0

limitPositiveNumber(value, options?) *

Converts and limits values to positive numbers (greater than zero).


map — Map Operations

ensureMap(data, options?) *

Converts various types of values to a Map.

ensureMap({ a: 1, b: 2 }); // Map { 'a' => 1, 'b' => 2 }
ensureMap([['a', 1]]); // Map { 'a' => 1 }
ensureMap(null); // Map {}

measure — Performance Measurement

measure(fn, options?)

Measures the execution time of a function.

const result = measure(() => heavyCalc(), { iteration: 100 });
console.log(result.time); // execution time (ms)

| Option | Type | Description | | ----------- | -------- | -------------------------------- | | iteration | number | Number of executions (default: 10) |


measureAsync(fn, options?)

Measures the execution time of an async function.


comparePerformance(fns, options?)

Compares the execution time of multiple functions.


comparePerformanceAsync(fns, options?)

Compares the execution time of multiple async functions.


number — Number

rangeClamp(value, min, max) *

Clamps a value to the min-max range.

rangeClamp(150, 0, 100); // 100
rangeClamp(-10, 0, 100); // 0

rangeLoop(value, min, max) *

When out of range, returns the value looped (modulo) back into range.

rangeLoop(12, 0, 10); // 2
rangeLoop(-1, 0, 10); // 9

rangeDefault(value, min, max, defaultValue) *

When out of range, returns the default value.


rangeMax(value, max) *

Returns the maximum value when the value exceeds it.


rangeMin(value, min) *

Returns the minimum value when the value falls below it.


rangePingpong(value, min, max) *

When out of range, returns the value ping-ponged (bounced) back into range.


interpolateNumber(value, ratio, options?) *

Returns a value interpolated between a base value and a target at the given ratio.

interpolateNumber(100, 0.5, { baseValue: 0 }); // 50
interpolateNumber(200, 0.25, { baseValue: 100 }); // 125

roundToStep(value, step) *

Rounds a value to the nearest step.

roundToStep(7, 5); // 5
roundToStep(8, 5); // 10

ensureNumber(value, options?) *

Converts a value to a number.


ensureRange(value, options?) *

Clamps a value to the specified range.


getValidMinMax(min, max)

Gets a valid min/max pair (with automatic ordering correction, etc.).


getValidNumber(value, options?) *

Validates and returns a valid number.


isWithinRange(value, min, max) *

Returns whether the value is ≥ min and ≤ max.


isStrictlyWithinRange(value, min, max) *

Returns whether the value is > min and < max.


object — Object Operations

get(data, path) *

Gets a nested property using dot or bracket notation.

get({ a: { b: { c: 42 } } }, 'a.b.c'); // 42
get({ arr: [1, 2, 3] }, 'arr[1]'); // 2

set(data, path, value) *

Returns a new object with the nested property set at the given path (immutable).

set({ a: { b: 1 } }, 'a.b', 99); // { a: { b: 99 } }

setMutable(data, path, value) *

Mutably sets the nested property at the given path.


unset(data, path) *

Returns a new object with the property at the given path removed (immutable).

unset({ a: 1, b: 2 }, 'a'); // { b: 2 }

unsetMutable(data, path) *

Mutably removes the property at the given path. Uses splice for arrays to compact the array.


update(data, values) *

Returns a new object with existing properties updated to new values (immutable).


updateMutable(data, values) *

Mutably updates existing own properties of an object. Returns the previous values.


omit(data, paths) *

Returns an object with the specified path properties omitted.

omit({ a: 1, b: 2, c: 3 }, ['b']); // { a: 1, c: 3 }

filterByKeys(target, condition, options?) *

Filters an object (recursively) to keep only entries whose keys contain the specified string.

filterByKeys({ name: 'Alice', age: 30 }, 'na');
// { name: 'Alice' }

| Option | Type | Description | | ----------- | --------- | ---------------------------------------------- | | normalize | boolean | Apply string normalization before comparison |


filterByValues(target, condition, options?) *

Filters an object (recursively) to keep only entries whose values contain the specified value.

filterByValues({ a: 'Alice', b: 'Bob', c: 1 }, 'Ali');
// { a: 'Alice' }
filterByValues({ a: 1, b: 2, c: 1 }, 1);
// { a: 1, c: 1 }

| Option | Type | Description | | ----------- | --------- | ---------------------------------------------------- | | normalize | boolean | Apply normalization before string comparison |


transformObject(source, rules, options?) *

Transforms and extracts object structure according to mapping rules.

transformObject({ firstName: 'Alice', age: 30 }, [
  { from: 'firstName', to: 'user.name' },
  { from: (s) => s.age * 2, to: 'doubleAge' },
]);
// { user: { name: 'Alice' }, doubleAge: 60 }

| Rule Property | Type | Description | | ------------------------ | -------------------- | --------------------------------------------- | | from | string \| Function | Path or function to compute the source value | | to | string \| Function | Path or function to transform the result | | shouldRemoveFromSource | boolean | When true, removes the source property |

| Option | Type | Description | | ------------------ | --------- | -------------------------------------------------- | | deleteSourceKeys | boolean | When true, removes source keys for all rules |


flattenObject(data, options?) *

Converts a nested object to a flat key-value pair structure.

flattenObject({ a: { b: { c: 1 } } });
// { 'a.b.c': 1 }

| Option | Type | Description | | -------------- | --------- | ---------------------------------------- | | keySeparator | string | Key separator character (default: '.') | | ignoreArray | boolean | When true, does not expand arrays |


distribute(data, rules, options?) *

Distributes object properties into multiple groups according to rules.


cloneDeep(data)

Deep-clones an object.


cloneShallow(data)

Shallow-clones an object. Supports Array, Map, Set, ArrayBuffer, TypedArray, DataView, Date, and RegExp.


createCaseInsensitiveObject(options?)

Creates a case-insensitive object (Proxy) where key lookups are case-insensitive.

const obj = createCaseInsensitiveObject({ target: { Name: 'Alice' } });
obj['name']; // 'Alice'
obj['NAME']; // 'Alice'
'name' in obj; // true

// caseSensitive: true makes keys case-sensitive
const sensitive = createCaseInsensitiveObject({
  target: { Name: 'Alice' },
  caseSensitive: true,
});
sensitive['name']; // undefined
sensitive['Name']; // 'Alice'

| Option | Type | Description | | ------------------ | ----------------------------- | ------------------------------------------------------------ | | target | object | Initial value object | | caseSensitive | boolean | When true, keys are case-sensitive (default: false) | | storedKeyType | 'transformed' \| 'original' | Key storage format | | isMutable | boolean | When true, directly modifies the original object | | includeInherited | boolean | When true, includes inherited properties |


createKeyTransformObject(transformKey, options?)

Creates an object (Proxy) that manages keys using a transform function. It is the foundation of createCaseInsensitiveObject.

// Object that stores all keys in uppercase
const obj = createKeyTransformObject((_, key) =>
  typeof key === 'string' ? key.toUpperCase() : key,
);
obj['name'] = 'Alice';
obj['NAME']; // 'Alice'

countKeys(data)

Returns the number of own properties of an object.


forEachValues(data, callback, options?) *

Executes a callback for each property value of an object. Stops if the callback returns false.

forEachValues({ a: 1, b: 2 }, (value) => {
  if (value === 2) return false; // stop
});

getByNormalizedKey(data, key, options?)

Gets an object value by a normalized key (e.g. ignoring case).


setByNormalizedKey(data, key, value, options?)

Sets a value in an object using a normalized key.


maybeAssign(target, source) *

Returns a new object with each property of source set in target (immutable).


maybeAssignMutable(target, source)

Mutably sets each property of source in target.


maybeDefault(target, defaults) *

Returns a new object with default values set for null/undefined properties in target.


maybeDefaultMutable(target, defaults, options?)

Mutably sets default values for null/undefined properties in target.

| Option | Type | Description | | --------------- | --------- | ------------------------------------------------------- | | overwriteNull | boolean | When true, also overwrites properties that are null |


maybeHasOwn(data, key)

Returns whether an object has the specified property as its own. Returns false when data is null.


stableStringify(data)

Returns a JSON string with the object's keys recursively sorted alphabetically.

stableStringify({ b: 2, a: 1 }); // '{"a":1,"b":2}'

needsDefineProperty(target, key, descriptor)

Determines whether a property definition needs to be applied.


setProperty(target, key, descriptor)

Defines a property using Object.defineProperty.


overrideInstance(target, overrides)

Overrides methods or properties of an instance.


string — String

normalizeString(value, options?) *

Normalizes a string to a unified representation. Useful for absorbing variation in search and comparison.

normalizeString('ABC', { ignoreWidth: true }); // 'abc'
normalizeString('アイウ', { ignoreKana: true }); // 'あいう'
normalizeString('Café', { ignoreDakuon: true }); // 'Cafe'
normalizeString('Hello World', { ignoreCase: true }); // 'hello world'

| Option | Type | Description | | --------------------- | --------- | -------------------------------------------------------- | | ignoreCase | boolean | Ignore case (unify to lowercase) | | ignoreWidth | boolean | Ignore full-width/half-width (unify to half-width) | | ignoreKana | boolean | Ignore katakana/hiragana (unify to hiragana) | | ignoreDakuon | boolean | Ignore voiced/semi-voiced consonant marks | | ignoreSokuon | boolean | Ignore geminate consonants (っ/ッ → つ/ツ) | | ignoreYouon | boolean | Ignore contracted sounds (ゃゅょ, etc.) | | ignoreChouon | boolean | Ignore long vowel marks (ー) | | ignoreLineFeed | boolean | Ignore line feeds | | ignoreSpace | boolean | Ignore spaces | | ignoreCompatibility | boolean | Normalize Unicode compatibility characters | | ignoreComposition | boolean | Normalize Unicode composed characters |


replacePlaceholders(template, values, options?) *

Replaces placeholders in a template string with values.

replacePlaceholders('Hello {{name}}, {{greeting}}!', {
  name: 'Alice',
  greeting: 'how are you',
});
// 'Hello Alice, how are you!'

replacePlaceholders('{{0}} and {{1}}', ['Alice', 'Bob']);
// 'Alice and Bob'

| Option | Type | Description | | -------------------- | ------------------ | ----------------------------------------------------------------- | | bracket | [string, string] | Placeholder bracket characters (default: ['{{', '}}']) | | removePlaceholders | boolean | When true, removes placeholders with no matching value | | flatKeys | boolean | When true, resolves with flat (non-nested) keys |


interpolateString(value, ratio, options?)

Interpolates a string animation-style (e.g. typing effect).

interpolateString('Hello', 0.6); // 'Hel'
interpolateString('World', 0.5, { initialValue: 'Hello' }); // intermediate value like 'HellWorld'

transformString(str, types, options?) *

Applies multiple transformation types to a string sequentially. You can combine case conversions and character type conversions.


replaceByMap(str, map, options?) *

Replaces all occurrences in a string according to a map (object or array).

replaceByMap('hello world', { hello: 'hi', world: 'earth' });
// 'hi earth'

createExtractor(bracket)

Creates a function that extracts parts surrounded by the specified bracket characters.

const extract = createExtractor(['{{', '}}']);
extract('{{name}} here'); // ['name']

Character Type Conversion

| Function | Description | Data Last | | ------------------------------ | ------------------------------------------------- | --------- | | retypeToFullWidth(str) | Half-width to full-width | ✓ | | retypeToHalfWidth(str) | Full-width to half-width | | | retypeToHiragana(str) | Katakana to hiragana | ✓ | | retypeToKatakana(str) | Hiragana to katakana | | | retypeToHiraganaSeion(str) | Katakana to hiragana (clear sounds only) | | | retypeToKatakanaSeion(str) | Hiragana to katakana (clear sounds only) | | | retypeToNoChouon(str) | Remove long vowel marks | | | retypeToNoLineFeed(str) | Remove line feeds | | | retypeToNoSpace(str) | Remove spaces | | | retypeToNfc(str) | NFC normalization | ✓ | | retypeToNfd(str) | NFD normalization | ✓ | | retypeToNfkc(str) | NFKC normalization | ✓ | | retypeToNfkd(str) | NFKD normalization | ✓ | | retype(str, types, options?) | Apply multiple character type conversions | |


Case Conversion

| Function | Description | Example | Data Last | | --------------------------- | -------------------- | ------------- | --------- | | recaseCamel(str) | camelCase | helloWorld | ✓ | | recasePascal(str) | PascalCase | HelloWorld | ✓ | | recaseSnake(str) | snake_case | hello_world | ✓ | | recaseScreamingSnake(str) | SCREAMING_SNAKE_CASE | HELLO_WORLD | ✓ | | recaseKebab(str) | kebab-case | hello-world | ✓ | | recaseTitle(str) | Title Case | Hello World | ✓ | | recaseLower(str) | lowercase | hello world | ✓ | | recaseUpper(str) | UPPERCASE | HELLO WORLD | ✓ | | lowerFirst(str) | Lowercase first char | helloWorld | ✓ | | upperFirst(str) | Uppercase first char | HelloWorld | ✓ |


Other String Utilities

| Function | Description | Data Last | | ----------------------------------------- | --------------------------------------------- | --------- | | ensureString(value) | Convert to string | ✓ | | escapeRegExp(str) | Escape special regex characters | | | isFullWidth(str) | Check if all characters are full-width | | | isHalfWidth(str) | Check if all characters are half-width | | | isLooseEqual(a, b, options?) | Check equality after normalizing strings | ✓ | | isSurroundedBy(str, prefix, suffix) | Check if surrounded by specified prefix/suffix | ✓ | | maybeReplace(str, pattern, replacement) | Replace only if the pattern matches | ✓ | | safeMatchAll(str, pattern) | Safely execute matchAll and return results | |


timer — Timer

debounce(fn, delay, options?)

Returns a debounce function that executes once after the specified time following the last call.

const onInput = debounce((value) => search(value), 300);
// .cancel() cancels the pending execution
// .flush()  executes immediately
// .isIdle() checks whether idle

throttle(fn, delay, options?)

Returns a throttle function that executes at most once per specified interval.

const onScroll = throttle((e) => update(e), 100);

sleep(duration)

Returns a Promise that waits for the specified number of milliseconds.

await sleep(1000); // wait 1 second

type — Type Checking

| Function | Description | Data Last | | ----------------------------------- | ----------------------------------------------------------------- | --------- | | isBlank(value) | Is null/undefined/empty string/whitespace-only string | | | isNullish(value) | Is null or undefined | | | isPresent(value) | Is not null/undefined | | | isUndefined(value) | Is undefined | | | isEmptyCollection(value) | Is empty Array/Map/Set | | | isEmptyValue(value) | Is null/undefined/empty string/empty array/empty object, etc. | | | isValidDate(value) | Is a valid Date object | | | isInvalidDate(value) | Is an invalid Date object (Invalid Date) | | | isValidNumber(value, options?) | Is a valid number (excluding NaN/Infinity) | | | isNumberLike(value) | Is a number or numeric string | | | isNonNegativeInteger(value) | Is a non-negative integer | | | isPrimitive(value) | Is a primitive type | | | isRegExp(value) | Is a RegExp | | | isIterable(value) | Is iterable | | | isAsyncIterable(value) | Is async iterable | | | getRawType(value) | Gets the internal type string from Object.prototype.toString | | | kind(value) | Gets the kind of value as a string | ✓ | | priority(value) | Gets the priority of the value as a number | ✓ | | ensureValidValue(value, options?) | Returns a fallback if the value is not valid | ✓ | | unsafeCast(value) | Type cast ignoring type checking | |


* Data Last support

License

MIT