Skip to content

Why 1o1-utils

Zero deps

Pure TypeScript. No transitive dependencies. No supply chain risk.

Ultra lightweight

2.1 kB total gzipped. Individual utilities weigh 139–366 bytes.

Ultra simple

Named object params. One function, one job. No config, no magic.

Ultra fast

Up to 11x faster than lodash. Every utility is benchmarked.

Verbose by design

Declarative, readable names. Code that explains itself without comments.


Every utility is implemented in pure TypeScript using only built-in language features. The entire dependency tree is… nothing.

"dependencies": {}

No transitive dependencies means no supply chain risk, no version conflicts, no surprise breaking changes from packages you’ve never heard of. What you install is what you get.

The entire library is 2.1 kB gzipped. For comparison, lodash is 70 kB and radash is 12 kB.

Each utility is a self-contained module you can import individually:

import { chunk } from "1o1-utils/chunk"; // 199 B
import { pick } from "1o1-utils/pick"; // 320 B
import { sleep } from "1o1-utils/sleep"; // 139 B
UtilitySize
sleep139 B
slugify147 B
isEmpty164 B
capitalize169 B
truncate170 B
arrayToHash173 B
unique173 B
groupBy180 B
debounce198 B
chunk199 B
deepMerge248 B
throttle258 B
pick320 B
retry321 B
transformCase330 B
sortBy350 B
omit366 B
Total2.1 kB

Every utility stays under strict size limits enforced in CI. If a PR makes a utility heavier, the build fails.

No positional args. No guessing what the second parameter does. Every function call reads like English:

// lodash — what's the 2nd argument?
_.chunk(array, 2);
_.truncate(str, { length: 20, separator: "..." });
_.sortBy(users, ["age"]);
// 1o1-utils — self-documenting
chunk({ array, size: 2 });
truncate({ str, length: 20, suffix: "..." });
sortBy({ array: users, key: "age" });

Each utility does exactly one thing. No overloaded signatures, no option objects with 15 fields, no implicit behavior. Read the source in under a minute.

Built with strict: true from day one. Full type inference, generics, and IntelliSense for every parameter — no @types/* package needed.

Function and parameter names are declarative and intentionally simple. You should never need to check the docs to understand what a call does:

// What does this do? You need to know the API.
_.keyBy(users, "id");
_.uniqBy(items, "sku");
_.get(obj, "a.b.c");
// What does this do? Read it out loud.
arrayToHash({ array: users, key: "id" });
unique({ array: items, key: "sku" });
pick({ obj, keys: ["a.b.c"] });

Names follow plain English — arrayToHash, not keyBy. unique, not uniqBy. deepMerge, not merge (which might or might not be deep). isEmpty, not empty (is it a verb or an adjective?).

Parameters are equally explicit: { array, key } instead of positional (collection, iteratee). { str, length, suffix } instead of (string, options). Every call site is self-documenting — your code becomes the documentation.

1o1-utils is consistently faster than lodash and radash on every operation it implements:

Utilityvs lodashvs radashvs native
chunk4.9x fasteron paron par
pick3.3x fasteron par
unique2.7x faster1.6x fasteron par
groupBy1.3x fasteron paron par
arrayToHashon paron paron par

On specific dataset sizes, chunk reaches up to 11.4x faster than lodash.

Every utility includes a benchmark file. Run pnpm bench to reproduce locally. See the full benchmark results for methodology and detailed numbers.


  • You need a few utility functions without the weight of a full library
  • You care about bundle size — every byte counts
  • You prefer self-documenting APIs with named parameters
  • You want TypeScript-first utilities with strict types
  • You don’t want to audit a dependency tree of 50+ packages