English | 简体中文
Opinionated shareable utils for different JavaScript/TypeScript projects. Requires node >= 14.18
.
npm install @modyqyw/utils
- Try deepmerge, deepmerge-ts or ts-deepmerge if you are looking for a merge solution.
- Try deepmerge, deepmerge-ts, ts-deepmerge, clone or structuredClone if you are looking for a clone solution.
Get value type name.
import { getType } from '@modyqyw/utils';
getType(null); // Null
getType(); // Undefined
getType(undefined); // Undefined
getType(true); // Boolean
getType(0); // Number
getType(0n); // BigInt
getType(''); // String
getType({}); // Object
getType([]); // Array
Determine if a value is a string.
import { isString } from '@modyqyw/utils';
isString(''); // true
isString(0); // false
isString(0n); // false
isString(true); // false
isString(undefined); // false
isString(null); // false
isString(Symbol()); // false
isString({}); // false
isString(() => {}); // false
isString([]); // false
You can check @sindresorhus/is for extra needs, such as is.xxx
and type assertions.
Determine if a value is a number.
import { isNumber } from '@modyqyw/utils';
isNumber(''); // false
isNumber(0); // true
isNumber(0n); // false
isNumber(true); // false
isNumber(undefined); // false
isNumber(null); // false
isNumber(Symbol()); // false
isNumber({}); // false
isNumber(() => {}); // false
isNumber([]); // false
You can check @sindresorhus/is for extra needs, such as is.xxx
and type assertions.
Determine if a value is a bigint.
import { isBigInt } from '@modyqyw/utils';
isBigInt(''); // false
isBigInt(0); // false
isBigInt(0n); // true
isBigInt(true); // false
isBigInt(undefined); // false
isBigInt(null); // false
isBigInt(Symbol()); // false
isBigInt({}); // false
isBigInt(() => {}); // false
isBigInt([]); // false
You can check @sindresorhus/is for extra needs, such as is.xxx
and type assertions.
Determine if a value is a boolean.
import { isBoolean } from '@modyqyw/utils';
isBoolean(''); // false
isBoolean(0); // false
isBoolean(0n); // false
isBoolean(true); // true
isBoolean(undefined); // false
isBoolean(null); // false
isBoolean(Symbol()); // false
isBoolean({}); // false
isBoolean(() => {}); // false
isBoolean([]); // false
You can check @sindresorhus/is for extra needs, such as is.xxx
and type assertions.
Determine if a value is undefined.
import { isUndefined } from '@modyqyw/utils';
isUndefined(''); // false
isUndefined(0); // false
isUndefined(0n); // false
isUndefined(true); // false
isUndefined(undefined); // true
isUndefined(null); // false
isUndefined(Symbol()); // false
isUndefined({}); // false
isUndefined(() => {}); // false
isUndefined([]); // false
You can check @sindresorhus/is for extra needs, such as is.xxx
and type assertions.
Determine if a value is null.
import { isNull } from '@modyqyw/utils';
isNull(''); // false
isNull(0); // false
isNull(0n); // false
isNull(true); // false
isNull(undefined); // false
isNull(null); // true
isNull(Symbol()); // false
isNull({}); // false
isNull(() => {}); // false
isNull([]); // false
You can check @sindresorhus/is for extra needs, such as is.xxx
and type assertions.
Determine if a value is null or undefined.
import { isNullish } from '@modyqyw/utils';
isNullish(''); // false
isNullish(0); // false
isNullish(0n); // false
isNullish(true); // false
isNullish(undefined); // true
isNullish(null); // true
isNullish(Symbol()); // false
isNullish({}); // false
isNullish(() => {}); // false
isNullish([]); // false
You can check @sindresorhus/is for extra needs, such as is.xxx
and type assertions.
Determine if a value is a symbol.
import { isSymbol } from '@modyqyw/utils';
isSymbol(''); // false
isSymbol(0); // false
isSymbol(0n); // false
isSymbol(true); // false
isSymbol(undefined); // false
isSymbol(null); // false
isSymbol(Symbol()); // true
isSymbol({}); // false
isSymbol(() => {}); // false
isSymbol([]); // false
You can check @sindresorhus/is for extra needs, such as is.xxx
and type assertions.
Determine if a value is a object.
import { isObject } from '@modyqyw/utils';
isObject(''); // false
isObject(0); // false
isObject(0n); // false
isObject(true); // false
isObject(undefined); // false
isObject(null); // false
isObject(Symbol()); // false
isObject({}); // true
isObject(() => {}); // false
isObject([]); // false
You can check @sindresorhus/is for extra needs, such as is.xxx
and type assertions.
Determine if a value is a function.
import { isFunction } from '@modyqyw/utils';
isFunction(''); // false
isFunction(0); // false
isFunction(0n); // false
isFunction(true); // false
isFunction(undefined); // false
isFunction(null); // false
isFunction(Symbol()); // false
isFunction({}); // false
isFunction(() => {}); // true
isFunction([]); // false
You can check @sindresorhus/is for extra needs, such as is.xxx
and type assertions.
Determine if a value is an array.
import { isArray } from '@modyqyw/utils';
isArray(''); // false
isArray(0); // false
isArray(0n); // false
isArray(true); // false
isArray(undefined); // false
isArray(null); // false
isArray(Symbol()); // false
isArray({}); // false
isArray(() => {}); // false
isArray([]); // true
You may want to determine if a value is an array and all of its items are numbers. Here is an example.
import { isArray, isNumber } from '@modyqyw/utils';
isArray([1, 2, 3], isNumber); // true
isArray([1, 2, '3'], isNumber); // false
You can check @sindresorhus/is for extra needs, such as is.xxx
and type assertions.
Determine if a value is a blob.
Determine if a value is a file.
Get millisecond-based timestamp.
import { getTimestamp } from '@modyqyw/utils';
const timestamp = getTimestamp();
Use Object.is
directly to determine if two values are equal. Use isDeepEqual if you need a deep comparison.
import { isEqual } from '@modyqyw/utils';
isEqual(null, null); // true
isEqual(undefined, null); // false
isEqual(undefined, undefined); // true
isEqual(true, true); // true
isEqual(false, false); // true
isEqual(true, false); // true
isEqual(1, 2); // false
isEqual(1, 1); // true
isEqual({}, {}); // false
isEqual({ a: 1 }, { a: 1, b: 2 }); // false
isEqual({ a: 1 }, { a: 1 }); // false
isEqual({ a: 1, b: { c: true } }, { a: 1, b: { c: true } }); // false
isEqual({ a: 1, b: { c: true } }, { a: 1, b: { c: false } }); // false
isEqual([], []); // false
isEqual([1, 2, 3, { a: 1, b: { c: true } }], [1, 2, 3, { a: 1, b: { c: true } }]); // false
isEqual([1, 2, 3, { a: 1, b: { c: true } }], [1, 2, 3, { a: 1, b: { c: false } }]); // false
Determine if two values are equal. For arrays, recursively determine the value corresponding to each index. For objects, recursively determine the value of each key. Other cases are determined with Object.is
.
import { isDeepEqual } from '@modyqyw/utils';
isDeepEqual(null, null); // true
isDeepEqual(undefined, null); // false
isDeepEqual(undefined, undefined); // true
isDeepEqual(true, true); // true
isDeepEqual(false, false); // true
isDeepEqual(true, false); // true
isDeepEqual(1, 2); // false
isDeepEqual(1, 1); // true
isDeepEqual({}, {}); // true
isDeepEqual({ a: 1 }, { a: 1, b: 2 }); // false
isDeepEqual({ a: 1 }, { a: 1 }); // true
isDeepEqual({ a: 1, b: { c: true } }, { a: 1, b: { c: true } }); // true
isDeepEqual({ a: 1, b: { c: true } }, { a: 1, b: { c: false } }); // false
isDeepEqual([], []); // true
isDeepEqual([1, 2, 3, { a: 1, b: { c: true } }], [1, 2, 3, { a: 1, b: { c: true } }]); // true
isDeepEqual([1, 2, 3, { a: 1, b: { c: true } }], [1, 2, 3, { a: 1, b: { c: false } }]); // false
Convert string to lower case.
import { lowerCase } from '@modyqyw/utils';
lowerCase(''); // ''
lowerCase('test'); // 'test'
lowerCase('TEST'); // 'test'
lowerCase('test string'); // 'test string'
lowerCase('TEST STRING'); // 'test string'
Convert string to locale lower case.
import { localeLowerCase } from '@modyqyw/utils';
localeLowerCase('STRING', 'en-US'); // 'string'
Convert first char to lower case.
import { lowerCaseFirst } from '@modyqyw/utils';
lowerCaseFirst(''); // ''
lowerCaseFirst('test'); // 'test'
lowerCaseFirst('TEST'); // 'tEST'
lowerCaseFirst('test string'); // 'test string'
lowerCaseFirst('TEST STRING'); // 'tEST STRING'
Convert string to upper case.
import { upperCase } from '@modyqyw/utils';
upperCase(''); // ''
upperCase('test'); // 'TEST'
upperCase('TEST'); // 'TEST'
upperCase('test string'); // 'TEST STRING'
upperCase('TEST STRING'); // 'TEST STRING'
Convert string to locale upper case.
import { localeLowerCase } from '@modyqyw/utils';
localeLowerCase('string', 'en-US'); // 'STRING'
Convert first char to upper case.
import { lowerCaseFirst } from '@modyqyw/utils';
lowerCaseFirst(''); // ''
lowerCaseFirst('test'); // 'test'
lowerCaseFirst('TEST'); // 'tEST'
lowerCaseFirst('test string'); // 'test string'
lowerCaseFirst('TEST STRING'); // 'tEST STRING'
Convert value to string. Try value.toString()
first, then Object#toString.call(value)
.
import { toString } from '@modyqyw/utils';
toString(undefined); // '[object Undefined]'
toString(null); // '[object Null]'
toString(0); // '0'
toString(Symbol('test')); // 'Symbol(test)'
toString([1, 2, 3]); // '1,2,3'
Same as Array#includes
. With better types. From ts-extras.
Convert value to an array.
import { toArray } from '@modyqyw/utils';
toArray(); // []
toArray(undefined); // []
toArray(null); // []
toArray(1); // [1]
toArray('abc'); // ['abc']
toArray({ a: 1, b: 2 }); // [{ a: 1, b: 2 }]
toArray([1, 2]); // [1, 2]
Find difference elements between two arrays. Pass a function to judge equation or fallback to Array#includes
. Return a new array.
import { difference, isDeepEqual } from '@modyqyw/utils';
difference([1, '2'], [1]); // ['2']
difference([1, '2', {}], [1, {}]); // ['2', {}]
difference([1, '2', { a: { b: 'c' } }], [1, { a: { b: 'c' } }]); // ['2', { a: { b: 'c' } }]
difference([1, '2', {}], [1, {}], isDeepEqual); // ['2']
difference([1, '2', { a: { b: 'c' } }], [1, { a: { b: 'c' } }], isDeepEqual); // ['2']
Find same elements between two arrays. Pass a function to judge equation or fallback to Array#includes
. Return a new array.
import { intersection, isDeepEqual } from '@modyqyw/utils';
intersection([1, '2'], [1]); // [1]
intersection([1, '2', {}], [1, {}]); // [1]
intersection([1, '2', { a: { b: 'c' } }], [1, { a: { b: 'c' } }]); // [1]
intersection([1, '2', {}], [1, {}], isDeepEqual); // [1, {}]
intersection([1, '2', { a: { b: 'c' } }], [1, { a: { b: 'c' } }], isDeepEqual); // [1, { a: { b: 'c' } }]
Find unique elements. Pass a function to judge equation or fallback to Set
. Return a new array.
import { uniq, isDeepEqual } from '@modyqyw/utils';
uniq([1, '2', 2, 2, '2']); // [1, '2', 2]
uniq([1, '2', 2, 2, '2', {}, {}]); // [1, '2', 2, {}, {}]
uniq([1, '2', 2, 2, '2', {}, {}], isDeepEqual); // [1, '2', 2, {}]
Find all different elements in two arrays. Use uniq
under the hood. Return a new array.
import { union, isDeepEqual } from '@modyqyw/utils';
union([1, '2'], [1, 3]); // [1, '2', 3]
union([1, '2', {}], [1, 3, {}]); // [1, '2', {}, 3, {}]
union([1, '2', { a: { b: 'c' } }], [1, 3, { a: { b: 'c' } }]); // [1, '2', { a: { b: 'c' } }, 3, { a: { b: 'c' } }])
union([1, '2', {}], [1, 3, {}], isDeepEqual); // [1, '2', {}, 3]
union([1, '2', { a: { b: 'c' } }], [1, 3, { a: { b: 'c' } }], isDeepEqual); // [1, '2', { a: { b: 'c' } }, 3]
Creates an array of numbers (positive and/or negative) progressing from start
up to, but not including end
.
start
is set to 0 by default. You can pass end
directly.
step
is set to 1 when start
< end
and -1 when start
>= end
by default.
Return a new array.
import { range } from '@modyqyw/utils';
range(4); // [0, 1, 2, 3]
range(-4); // [0, -1, -2, -3]
range(1, 5); // [1, 2, 3, 4]
range(0, 20, 5); // [0, 5, 10, 15]
range(0, -4, -1); // [0, -1, -2, -3]
range(1, 4, 0); // [1, 1, 1]
range(0); // []
Same as Object.keys
. With better types. From ts-extras.
Same as Object.entries
. With better types. From ts-extras.
Same as Object.fromEntries
. With better types. From ts-extras.
Same as Set#has
. With better types. From ts-extras.
You can check promise-fun for extra needs.
Sleep 💤, then call callback
if passed.
import { sleep } from '@modyqyw/utils';
await sleep(1000); // sleep 1s
await sleep(1000, () => {
console.log('Hi.');
}); // sleep 1s, then log `Hi.`
Creates a throttled function that only invokes callback
at most once per every delay
milliseconds.
import { throttle } from '@modyqyw/utils';
const throttled = throttle(fn, 1000);
throttled(); // called
throttled();
throttled();
throttled(); // called
setTimeout(throttled, 1200); // called
You can disable leading
or trailing
in the third param. Default { leading: true, trailing: true }
.
import { throttle } from '@modyqyw/utils';
const throttled = throttle(fn, 1000, { trailing: false });
throttled(); // called
throttled();
throttled();
throttled();
setTimeout(throttled, 1200); // called
import { throttle } from '@modyqyw/utils';
const throttled = throttle(fn, 1000, { leading: false });
throttled();
throttled();
throttled();
throttled(); // called
setTimeout(throttled, 1200); // called
import { throttle } from '@modyqyw/utils';
const throttled = throttle(fn, 1000, { leading: false, trailing: false });
throttled();
throttled();
throttled();
throttled();
setTimeout(throttled, 1200);
Use .abort()
to abort next invocations. Pass true
to abort the next invocation.
import { throttle } from '@modyqyw/utils';
const throttled = throttle(fn, 1000);
throttled(); // called
throttled();
throttled.abort(true);
throttled(); // called
throttled.abort();
throttled();
throttled();
See David Corbacho's article for details over the differences between throttle and debounce.
Creates a debounced function that delays invoking callback
until after delay
milliseconds have elapsed since the last time the debounced function was invoked.
import { debounce } from '@modyqyw/utils';
const debounced = debounce(fn, 1000);
debounced();
debounced();
debounced();
debounced(); // called
setTimeout(debounced, 1200); // called
You can disable leading
or trailing
in the third param. Default { leading: false, trailing: true }
.
import { debounce } from '@modyqyw/utils';
const debounced = debounce(fn, 1000, { leading: false, trailing: false });
debounced();
debounced();
debounced();
debounced();
setTimeout(debounced, 1200);
import { debounce } from '@modyqyw/utils';
const debounced = debounce(fn, 1000, { leading: true, trailing: true });
debounced(); // called
debounced();
debounced();
debounced(); // called
setTimeout(debounced, 1200); // called
import { debounce } from '@modyqyw/utils';
const debounced = debounce(fn, 1000, { leading: true, trailing: false });
debounced(); // called
debounced();
debounced();
debounced();
setTimeout(debounced, 1200); // called
Use .abort()
to abort next invocations. Pass true
to abort the next invocation.
import { debounce } from '@modyqyw/utils';
const debounced = debounce(fn, 1000);
debounced();
debounced();
debounced.abort(true);
debounced(); // called
debounced.abort();
debounced();
debounced();
Performs left-to-right function composition.
import { pipe } from '@modyqyw/utils';
const fn = pipe(
(a: number, b: number) => a + b, // first do
(a) => Math.pow(a, 2), // second do
(a) => a * 3,
(a) => a / 4,
(a) => a - 2,
);
fn(1, 1); // 1
Empty function.
import { noop } from '@modyqyw/utils';
// nothing happen
noop();
You can check type-fest, ts-toolbelt and ts-essentials for extra needs.
type AnyRecord = Record<string, any>;
type Falsy = false | 0 | 0n | '' | null | undefined;
type MaybePromise<T> = T | Promise<T>;
type MaybePromiseLike<T> = T | PromiseLike<T>;
type Promisable<T> = T | PromiseLike<T>;
type Awaitable<T> = T | PromiseLike<T>;
type MaybeNull<T> = T | null;
type Nullable<T> = T | null;
This is not the same as TypeScript NonNullable.
type NonNullable<T> = Exclude<T, null>;
type MaybeUndefined<T> = T | undefined;
type Optional<T> = T | undefined;
type Undefinable<T> = Optional<T>;
type Nullish<T> = T | undefined | null;
This is the same as TypeScript NonNullable.
type NonNullish<T> = Exclude<T, undefined | null>;
type MaybeArray<T> = T | Array<T>;
type Arrayable<T> = T | Array<T>;
type ElementOf<T> = T extends (infer E)[] ? E : never;
type Fn = () => void;
type PromisifyFn<T extends Fn> = () => Promise<ReturnType<T>>;
type AnyFn<T = any> = (...args: any[]) => T;
type PromisifyAnyFn<T extends AnyFn> = (...args: Parameters<T>) => Promise<ReturnType<T>>;
Inspired by @antfu/utils.
I have checked and learned from these libraries. Thanks a lot! Check them for more if you need.