# utils **Repository Path**: ModyQyW/utils ## Basic Information - **Project Name**: utils - **Description**: 不同 JavaScript/TypeScript 项目的可共享工具方法。 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-06-01 - **Last Updated**: 2023-12-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # @modyqyw/utils [![License](https://img.shields.io/github/license/ModyQyW/utils)](https://github.com/ModyQyW/utils/blob/main/LICENSE) [![npm](https://img.shields.io/npm/v/@modyqyw/utils)](https://www.npmjs.com/package/@modyqyw/utils/) [English](./README.md) | 简体中文 开箱即用的工具方法,适用于不同的 JavaScript / TypeScript 项目。要求 `node >= 14.18`。 ## 安装 ```shell npm install @modyqyw/utils ``` ## API ### base - 如果你正在寻找一个关于合并 merge 的解决方案,请尝试 [deepmerge](https://github.com/TehShrike/deepmerge)、[deepmerge-ts](https://github.com/RebeccaStevens/deepmerge-ts) 或 [ts-deepmerge](https://github.com/voodoocreation/ts-deepmerge)。 - 如果你正在寻找一个关于克隆 clone 的解决方案,请尝试 [deepmerge](https://github.com/TehShrike/deepmerge)、[deepmerge-ts](https://github.com/RebeccaStevens/deepmerge-ts)、[ts-deepmerge](https://github.com/voodoocreation/ts-deepmerge)、[clone](https://github.com/pvorb/clone) 或 [structuredClone](https://developer.mozilla.org/docs/Web/API/structuredClone)。 ### getType 获取值的类型名称。 ```typescript 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 ``` #### isString 判断一个值是否为 string。 ```typescript 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 ``` 如果你有额外需求,比如 `ix.xxx` 和类型断言,请查看 [@sindresorhus/is](https://github.com/sindresorhus/is)。 #### isNumber 判断一个值是否为 number。 ```typescript 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 ``` 如果你有额外需求,比如 `ix.xxx` 和类型断言,请查看 [@sindresorhus/is](https://github.com/sindresorhus/is)。 #### isBigInt 判断一个值是否为 bigint。 ```typescript 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 ``` 如果你有额外需求,比如 `ix.xxx` 和类型断言,请查看 [@sindresorhus/is](https://github.com/sindresorhus/is)。 #### isBoolean 判断一个值是否为 boolean。 ```typescript 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 ``` 如果你有额外需求,比如 `ix.xxx` 和类型断言,请查看 [@sindresorhus/is](https://github.com/sindresorhus/is)。 #### isUndefined 判断一个值是否为 undefined。 ```typescript 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 ``` 如果你有额外需求,比如 `ix.xxx` 和类型断言,请查看 [@sindresorhus/is](https://github.com/sindresorhus/is)。 #### isNull 判断一个值是否为 null。 ```typescript 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 ``` 如果你有额外需求,比如 `ix.xxx` 和类型断言,请查看 [@sindresorhus/is](https://github.com/sindresorhus/is)。 #### isNullish 判断一个值是否为 null 或 undefined。 ```typescript 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 ``` 如果你有额外需求,比如 `ix.xxx` 和类型断言,请查看 [@sindresorhus/is](https://github.com/sindresorhus/is)。 #### isSymbol 判断一个值是否为 symbol。 ```typescript 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 ``` 如果你有额外需求,比如 `ix.xxx` 和类型断言,请查看 [@sindresorhus/is](https://github.com/sindresorhus/is)。 #### isObject 判断一个值是否为 object。 ```typescript 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 ``` 如果你有额外需求,比如 `ix.xxx` 和类型断言,请查看 [@sindresorhus/is](https://github.com/sindresorhus/is)。 #### isFunction 判断一个值是否为 function。 ```typescript 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 ``` 如果你有额外需求,比如 `ix.xxx` 和类型断言,请查看 [@sindresorhus/is](https://github.com/sindresorhus/is)。 #### isArray 判断一个值是否为 array。 ```typescript 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 ``` 你可能想要判断一个值是否为 array 且所有元素是否为 number,以下是一个例子。 ```typescript import { isArray, isNumber } from '@modyqyw/utils'; isArray([1, 2, 3], isNumber); // true isArray([1, 2, '3'], isNumber); // false ``` 如果你有额外需求,比如 `ix.xxx` 和类型断言,请查看 [@sindresorhus/is](https://github.com/sindresorhus/is)。 #### isBlob 判断一个值是否为 blob。 #### isFile 判断一个值是否为 file。 #### getTimestamp 获取毫秒级时间戳。 ```typescript import { getTimestamp } from '@modyqyw/utils'; const timestamp = getTimestamp(); ``` #### isEqual 直接使用 `Object.is` 来判断两个值是否相等。如果你需要深层比较,请使用 [isDeepEqual](#isdeepequal)。 ```typescript 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 ``` #### isDeepEqual 判断两个值是否相等。对于数组,递归地判断每个下标的值。对于对象,递归地判断每个键对应的值。其它情况使用 `Object.is` 来判断。 ```typescript 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 ``` ### string #### lowerCase 将字符串转换成小写。 ```typescript import { lowerCase } from '@modyqyw/utils'; lowerCase(''); // '' lowerCase('test'); // 'test' lowerCase('TEST'); // 'test' lowerCase('test string'); // 'test string' lowerCase('TEST STRING'); // 'test string' ``` #### localeLowerCase 将字符串转换成本地小写。 ```typescript import { localeLowerCase } from '@modyqyw/utils'; localeLowerCase('STRING', 'en-US'); // 'string' ``` #### lowerCaseFirst 将第一个字符转换成小写。 ```typescript import { lowerCaseFirst } from '@modyqyw/utils'; lowerCaseFirst(''); // '' lowerCaseFirst('test'); // 'test' lowerCaseFirst('TEST'); // 'tEST' lowerCaseFirst('test string'); // 'test string' lowerCaseFirst('TEST STRING'); // 'tEST STRING' ``` #### upperCase 将字符串转换成大写。 ```typescript import { upperCase } from '@modyqyw/utils'; upperCase(''); // '' upperCase('test'); // 'TEST' upperCase('TEST'); // 'TEST' upperCase('test string'); // 'TEST STRING' upperCase('TEST STRING'); // 'TEST STRING' ``` #### localeUpperCase 将字符串转换成本地大写。 ```typescript import { localeLowerCase } from '@modyqyw/utils'; localeLowerCase('string', 'en-US'); // 'STRING' ``` #### upperCaseFirst 将第一个字符转换成大写。 ```typescript import { lowerCaseFirst } from '@modyqyw/utils'; lowerCaseFirst(''); // '' lowerCaseFirst('test'); // 'test' lowerCaseFirst('TEST'); // 'tEST' lowerCaseFirst('test string'); // 'test string' lowerCaseFirst('TEST STRING'); // 'tEST STRING' ``` #### toString 将值转换成字符串。首先尝试 `value.toString()`,然后再尝试 `Object#toString.call(value)`。 ```typescript 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' ``` ### array #### arrayIncludes 和 `Array#includes` 一致,但拥有更好的类型。来源于 [ts-extras](https://github.com/sindresorhus/ts-extras)。 #### toArray 将值转换成数组。 ```typescript 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] ``` #### difference 找到两个数组中不同的元素。内部默认使用 `Array#includes` 判断相等性,你也可以传入一个自定义方法。返回一个新数组。 ```typescript 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'] ``` #### intersection 找到两个数组中相同的元素。内部默认使用 `Array#includes` 判断相等性,你也可以传入一个自定义方法。返回一个新数组。 ```typescript 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' } }] ``` #### uniq 数组去重。内部默认使用 `Array#includes` 判断相等性,你也可以传入一个自定义方法。返回一个新数组。 ```typescript 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, {}] ``` #### union 找到两个数组所有不同元素。内部使用 `uniq`。返回一个新数组。 ```typescript 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] ``` #### range 创建一个从 `start` 到不包括 `end` 的数组。 `start` 默认设置为 0,你可以直接传入 `end`。 当 `start` < `end` 时,`step` 默认为 1,否则默认为 -1。 返回一个新数组。 ```typescript 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); // [] ``` ### object #### objectKeys 和 `Object.keys` 一致,但拥有更好的类型。来源于 [ts-extras](https://github.com/sindresorhus/ts-extras)。 #### objectEntries 和 `Object.entries` 一致,但拥有更好的类型。来源于 [ts-extras](https://github.com/sindresorhus/ts-extras)。 #### objectFromEntries 和 `Object.fromEntries` 一致,但拥有更好的类型。来源于 [ts-extras](https://github.com/sindresorhus/ts-extras)。 ### set #### setHas 和 `Set#has` 一致,但拥有更好的类型。来源于 [ts-extras](https://github.com/sindresorhus/ts-extras)。 ### promise 如果你有额外需求,请查看 [promise-fun](https://github.com/sindresorhus/promise-fun)。 #### sleep 休眠 💤,之后如果传递了 `callback` 就会调用它。 ```typescript import { sleep } from '@modyqyw/utils'; await sleep(1000); // sleep 1s await sleep(1000, () => { console.log('Hi.'); }); // sleep 1s, then log `Hi.` ``` ### function #### throttle 创建一个节流函数,每 `delay` 毫秒最多只调用一次 `callback`。 ```typescript import { throttle } from '@modyqyw/utils'; const throttled = throttle(fn, 1000); throttled(); // called throttled(); throttled(); throttled(); // called setTimeout(throttled, 1200); // called ``` 你可以在第三个参数中禁用 `leading` 或 `trailing`,默认为 `{ leading: true, trailing: true }`。 ```typescript import { throttle } from '@modyqyw/utils'; const throttled = throttle(fn, 1000, { trailing: false }); throttled(); // called throttled(); throttled(); throttled(); setTimeout(throttled, 1200); // called ``` ```typescript import { throttle } from '@modyqyw/utils'; const throttled = throttle(fn, 1000, { leading: false }); throttled(); throttled(); throttled(); throttled(); // called setTimeout(throttled, 1200); // called ``` ```typescript import { throttle } from '@modyqyw/utils'; const throttled = throttle(fn, 1000, { leading: false, trailing: false }); throttled(); throttled(); throttled(); throttled(); setTimeout(throttled, 1200); ``` 使用 `.abort()` 中止下一次调用,传入 `true` 表示中止之后所有调用。 ```typescript import { throttle } from '@modyqyw/utils'; const throttled = throttle(fn, 1000); throttled(); // called throttled(); throttled.abort(true); throttled(); // called throttled.abort(); throttled(); throttled(); ``` 你可以在 [这里](https://css-tricks.com/debouncing-throttling-explained-examples/) 了解更多节流和防抖的区别。 #### debounce 创建一个防抖函数,自上次调用以来过去了 `delay` 毫秒再调用 `callback`。 ```typescript import { debounce } from '@modyqyw/utils'; const debounced = debounce(fn, 1000); debounced(); debounced(); debounced(); debounced(); // called setTimeout(debounced, 1200); // called ``` 你可以在第三个参数中禁用 `leading` 或 `trailing`,默认为 `{ leading: false, trailing: true }`。 ```typescript import { debounce } from '@modyqyw/utils'; const debounced = debounce(fn, 1000, { leading: false, trailing: false }); debounced(); debounced(); debounced(); debounced(); setTimeout(debounced, 1200); ``` ```typescript import { debounce } from '@modyqyw/utils'; const debounced = debounce(fn, 1000, { leading: true, trailing: true }); debounced(); // called debounced(); debounced(); debounced(); // called setTimeout(debounced, 1200); // called ``` ```typescript import { debounce } from '@modyqyw/utils'; const debounced = debounce(fn, 1000, { leading: true, trailing: false }); debounced(); // called debounced(); debounced(); debounced(); setTimeout(debounced, 1200); // called ``` 使用 `.abort()` 中止下一次调用,传入 `true` 表示中止之后所有调用。 ```typescript import { debounce } from '@modyqyw/utils'; const debounced = debounce(fn, 1000); debounced(); debounced(); debounced.abort(true); debounced(); // called debounced.abort(); debounced(); debounced(); ``` 你可以在 [这里](https://css-tricks.com/debouncing-throttling-explained-examples/) 了解更多节流和防抖的区别。 #### pipe 执行从左到右的函数组合。 ```typescript 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 ``` #### noop 空函数。 ```typescript import { noop } from '@modyqyw/utils'; // nothing happen noop(); ``` ### types 如果你有额外需求,请查看 [type-fest](https://github.com/sindresorhus/type-fest)、[ts-toolbelt](https://github.com/millsp/ts-toolbelt) 和 [ts-essentials](https://github.com/ts-essentials/ts-essentials)。 #### AnyRecord ```typescript type AnyRecord = Record; ``` #### Falsy ```typescript type Falsy = false | 0 | 0n | '' | null | undefined; ``` #### MaybePromise ```typescript type MaybePromise = T | Promise; ``` #### MaybePromiseLike ```typescript type MaybePromiseLike = T | PromiseLike; ``` #### Promisable ```typescript type Promisable = T | PromiseLike; ``` #### Awaitable ```typescript type Awaitable = T | PromiseLike; ``` #### MaybeNull ```typescript type MaybeNull = T | null; ``` #### Nullable ```typescript type Nullable = T | null; ``` #### NonNullable **这个类型和 TypeScript 自带的 [NonNullable](https://www.typescriptlang.org/docs/handbook/utility-types.html#nonnullabletype) 不一样。** ```typescript type NonNullable = Exclude; ``` #### MaybeUndefined ```typescript type MaybeUndefined = T | undefined; ``` #### Optional ```typescript type Optional = T | undefined; ``` #### Undefinable ```typescript type Undefinable = Optional; ``` #### Nullish ```typescript type Nullish = T | undefined | null; ``` #### NonNullish **这个类型和 TypeScript 自带的 [NonNullable](https://www.typescriptlang.org/docs/handbook/utility-types.html#nonnullabletype) 一样。** ```typescript type NonNullish = Exclude ``` #### MaybeArray ```typescript type MaybeArray = T | Array; ``` #### Arrayable ```typescript type Arrayable = T | Array; ``` #### ElementOf ```typescript type ElementOf = T extends (infer E)[] ? E : never; ``` #### Fn ```typescript type Fn = () => void; ``` #### PromisifyFn ```typescript type PromisifyFn = () => Promise>; ``` #### AnyFn ```typescript type AnyFn = (...args: any[]) => T; ``` #### PromisifyAnyFn ```typescript type PromisifyAnyFn = (...args: Parameters) => Promise>; ``` ## 致谢 灵感源自 [@antfu/utils](https://github.com/antfu/utils)。 我已经查看并学习了这些库。非常感谢维护者们的付出!如果需要,请查看它们以了解更多信息。 - [lodash](https://lodash.com/) - [ramda](https://ramdajs.com/) - [remeda](https://remedajs.com/) - [fp-ts](https://gcanti.github.io/fp-ts/) - [io-ts](https://gcanti.github.io/io-ts/) - [change-case](https://github.com/blakeembrey/change-case) - [promise-fun](https://github.com/sindresorhus/promise-fun) - [rxjs](https://rxjs.dev/) - [mlly](https://github.com/unjs/mlly) - [pkg-types](https://github.com/unjs/pkg-types) - [local-pkg](https://github.com/antfu/local-pkg) - [type-fest](https://github.com/sindresorhus/type-fest) - [ts-essentials](https://github.com/ts-essentials/ts-essentials) - [ts-toolbelt](https://github.com/millsp/ts-toolbelt) - [throttle-debounce](https://github.com/niksy/throttle-debounce) - [js-sdsl](https://js-sdsl.org/) - [joi](https://joi.dev/) - [zod](https://zod.dev/) - [yup](https://github.com/jquense/yup) ## [赞助者们](https://github.com/ModyQyW/sponsors)