@antfu/utils
Opinionated collection of type-safe, tree-shakable JavaScript/TypeScript utility functions and generic types from Anthony Fu, meant to be bundled straight into your own library.
Repository Health
Technical Analysis
@antfu/utils is an opinionated collection of common JavaScript and TypeScript helper functions maintained by Anthony Fu (Vue core team, creator of Vite plugins, VueUse, and UnoCSS). It bundles small, focused utilities for arrays, objects, strings, promises, math, and runtime type guards behind a single tree-shakable ESM entry point, along with reusable TypeScript type helpers like Arrayable<T>, Nullable<T>, and ElementOf<T>.
The package is explicitly designed to be installed as a devDependency and bundled directly into your own library’s dist output rather than shipped as a runtime dependency, keeping consumers’ dependency trees flat. It has become a de facto foundation used across many of Anthony Fu’s own open-source projects (VueUse, UnoCSS, Slidev, Vitesse) and is a common building block for other TypeScript tooling authors who want dependable, well-typed micro-utilities without pulling in a much larger general-purpose library.
What You Get
- Array helpers like toArray, flattenArrayable, mergeArrayable, and multi-way partition for working with values that may or may not already be arrays
- Object utilities including objectPick, objectOmit, deepMerge, deepMergeWithArray, and clearUndefined for shaping and merging plain objects
- Promise and async primitives such as sleep, createSingletonPromise, createControlledPromise, and createPromiseLock for coordinating async flows
- A full suite of type guards (isString, isFunction, isObject, isDef, notNullish, isTruthy) with correct TypeScript type narrowing
- Reusable generic TypeScript types (Arrayable<T>, Nullable<T>, Awaitable<T>, ElementOf<T>, DeepMerge<F,S>) usable independently of the runtime functions
- String helpers (template, slash, ensurePrefix/ensureSuffix, capitalize, randomStr) and math helpers (clamp, sum, lerp, remap)
Common Use Cases
- Building a library or CLI tool and wanting small, dependency-free, tree-shaken utility functions bundled directly into your dist rather than adding a runtime dependency
- Normalizing function or CLI arguments that may be a single value or an array using toArray/mergeArrayable/flattenArrayable
- Writing type-safe runtime guards (isString, isObject, notNullish) that also narrow TypeScript types at compile time
- Coordinating async initialization exactly once across a module using createSingletonPromise, or exposing a promise whose resolve/reject can be called externally via createControlledPromise
- Picking, omitting, or deep-merging configuration objects (objectPick, objectOmit, deepMerge) when composing user config with defaults
Under The Hood
Architecture A single ESM entry point (src/index.ts) re-exports 13 focused modules organized strictly by domain (array, base, equal, function, guards, is, math, object, p, promise, string, time, types, vendor) — there’s no plugin system, no runtime configuration object, and no shared internal state beyond a couple of small factories. The two notable pieces of internal structure are PInstance, a class extending the native Promise to power the concurrency-limited p() async batch helper (built on p-limit), and createControlledPromise/createSingletonPromise, closures that wrap a Promise executor to expose external resolve/reject or memoize a promise-returning function. sideEffects: false in package.json enables per-function tree-shaking for consumers.
Tech Stack Written in TypeScript ~5.9 and built with unbuild 3.x on top of Rollup, producing a single ESM-only dist/index.mjs plus .d.mts declarations (node16 resolution) — no CJS output. Tests run on Vitest 3, linting goes through @antfu/eslint-config, and releases are cut with bumpp. Runtime footprint is intentionally minimal: only two dependencies get inlined into dist at build time via Rollup’s inlineDependencies — throttle-debounce (wrapped in vendor.ts for the throttle/debounce exports) and p-limit (used inside p.ts) — everything else in package.json is devDependencies, so consumers never install anything transitively.
Code Quality Vitest test files exist for 7 of the 13 domain modules (array, function, is, math, object, p, promise, string) with committed snapshot files under src/snapshots, but guards.ts, equal.ts, base.ts, time.ts, types.ts, and vendor.ts have no dedicated tests. Every exported function and type carries a TSDoc comment with an @category tag (surfaced via jsdocs.io), and overloaded signatures — partition with 1-6 filter functions, template with object vs. positional-args forms — are hand-written rather than generated. Naming is terse and consistent (isX for guards, objectX for object helpers), and error handling is minimal by design: assert() throws on failed conditions, but most functions favor permissive behavior (e.g. toArray treats null/undefined as an empty array) over throwing.
API Design The API is a flat, uncurried collection of roughly 40 standalone functions grouped only by filename, not namespaces — you import { toArray, isString, deepMerge } from '@antfu/utils' directly with no configuration object or factory step. Function names follow a consistent verbNoun/isNoun convention, and generic type parameters are inferred in nearly all cases so call sites rarely need explicit type annotations. Because it’s designed as a devDependency bundled into a consumer’s own dist, there’s no runtime installation ceremony for end users of libraries built on top of it — only the library author interacts with the package directly. Documentation lives entirely in TSDoc comments plus a short README, with one longer usage doc (docs/p.md) for the more complex p() concurrency helper, and no dedicated docs site beyond the auto-generated jsdocs.io reference.
Used by 2 apps in this directory
Kimi Code CLI
AI Code Assistants · AI Agents · Developer Tools
A single-binary, terminal-native coding agent that reads, edits, and runs code end to end, built by Moonshot AI for Kimi models but pluggable with Anthropic, OpenAI, and Google providers too.
Novu
Developer Tools
Open-source communication infrastructure that connects your products and AI agents to every channel your users live on — Inbox, Email, SMS, Push, Chat, and more.