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

@typesugar/std

v0.1.0

Published

🧊 Standard typeclasses and extension methods for enriching basic TypeScript types

Readme

@typesugar/std

Standard library extensions for TypeScript.

Overview

@typesugar/std provides a comprehensive set of typeclasses, extension methods, data types, and macros for enriching basic TypeScript types. Draws from the best of Haskell, Scala, Rust, Kotlin, Swift, and commonly-requested JS/TS utilities.

Installation

npm install @typesugar/std
# or
pnpm add @typesugar/std

Usage

Extension Methods (Scala 3-style)

Extension methods are import-scoped. Import a namespace or function from @typesugar/std and the transformer automatically resolves undefined method calls against what's in scope:

import { extend } from "typesugar";
import { NumberExt, StringExt, ArrayExt } from "@typesugar/std";

// extend() with namespace imports
extend(42).clamp(0, 100); // β†’ NumberExt.clamp(42, 0, 100)
extend(255).toHex(); // β†’ NumberExt.toHex(255)
extend(7).isPrime(); // β†’ NumberExt.isPrime(7)

extend("hello world").capitalize(); // β†’ StringExt.capitalize("hello world")

extend([1, 2, 3, 4, 5]).chunk(2); // β†’ ArrayExt.chunk([1, 2, 3, 4, 5], 2)
extend([3, 1, 4, 1, 5]).unique(); // β†’ ArrayExt.unique([3, 1, 4, 1, 5])

Implicit extension rewriting (no extend() needed):

import { NumberExt } from "@typesugar/std";

(42).clamp(0, 100); // β†’ NumberExt.clamp(42, 0, 100)
(7).isPrime(); // β†’ NumberExt.isPrime(7)

Bare function imports work too:

import { clamp, isPrime } from "@typesugar/std";

(42).clamp(0, 100); // β†’ clamp(42, 0, 100)
clamp(42, 0, 100); // also works as a direct call

Ranges (Scala/Kotlin-style)

import { range, rangeToArray } from "@typesugar/std";
rangeToArray(range(1, 10)); // [1, 2, ..., 9]

FlatMap Typeclass

The FlatMap typeclass provides sequencing/chaining operations for type constructors. It's the minimal typeclass required for the let:/yield: and par:/yield: do-notation macros.

import { registerFlatMap, getFlatMap } from "@typesugar/std";

// Built-in instances for Array, Promise, Iterable, AsyncIterable
const arrayFlatMap = getFlatMap("Array");

// Register custom instances
registerFlatMap("Option", {
  map: (fa, f) => fa.map(f),
  flatMap: (fa, f) => fa.flatMap(f),
});

Do-Notation Macros

Two labeled block macros for effect-based programming:

  • let:/yield: β€” Sequential (monadic) comprehensions with flatMap chains
  • par:/yield: β€” Parallel (applicative) comprehensions with Promise.all or .map()/.ap()

let:/yield: β€” Sequential Comprehensions

Bindings can depend on previous bindings. Supports guards, fallbacks, discard bindings, and pure map steps.

let: {
  user << fetchUser(id); // Monadic bind
  posts << fetchPosts(user.id); // Depends on user
  if (posts.length > 0) {
  } // Guard
  first = posts[0]; // Pure map step
}
yield: ({ user, first });

// Compiles to:
// fetchUser(id).then(user =>
//   fetchPosts(user.id).then(posts =>
//     posts.length > 0
//       ? ((first) => ({ user, first }))(posts[0])
//       : undefined))

orElse Fallback

let: {
  config << loadConfig() || defaultConfig(); // Fallback on error
}
yield: {
  config;
}

Discard Binding

let: {
  _ << log("Starting..."); // Execute but discard result
  x << computation();
}
yield: {
  x;
}

par:/yield: β€” Parallel Comprehensions

All bindings must be independent. Uses Promise.all for Promises, .map()/.ap() for other applicative types.

par: {
  user << fetchUser(id);
  config << loadConfig();
  posts << fetchPosts();
}
yield: ({ user, config, posts });

// Compiles to:
// Promise.all([fetchUser(id), loadConfig(), fetchPosts()])
//   .then(([user, config, posts]) => ({ user, config, posts }))

Why par: instead of let:?

  1. Parallel execution: Promises run concurrently via Promise.all
  2. Error accumulation: Validation types collect ALL errors, not just the first
  3. Compile-time independence check: The macro catches dependencies at build time

With Custom Types

Any type with a registered FlatMap instance works with both macros:

import { registerFlatMap } from "@typesugar/std";

registerFlatMap("Option", {
  map: (fa, f) => fa.map(f),
  flatMap: (fa, f) => fa.flatMap(f),
});

// Now Option works with let:/yield:
let: {
  x << some(5);
  y << some(x * 2);
}
yield: ({ x, y });

Extension Methods

Rich extension methods for every basic type:

| Type | Methods | | --------------- | ------------------------------------------------------------------ | | NumberExt | 45+ methods: clamp, toHex, isPrime, times, abs, ... | | StringExt | 50+ methods: capitalize, toSnakeCase, truncate, words, ... | | ArrayExt | 50+ methods: chunk, unique, groupBy, partition, zip, ... | | ObjectExt | 30+ methods: pick, omit, mapValues, deepMerge, ... | | BooleanExt | 20+ methods: toInt, and, or, implies, ... | | DateExt | 40+ methods: addDays, startOfMonth, format, isWeekend, ... | | MapExt | 15+ methods: mapValues, filterKeys, merge, ... | | PromiseExt | 20+ methods: tap, timeout, retry, mapError, ... | | FunctionExt | 25+ methods: memoize, debounce, throttle, compose, ... |

Data Types

Tuples

import { pair, triple, fst, snd, bimap, swap } from "@typesugar/std";

const p = pair(1, "hello");
fst(p); // 1
snd(p); // "hello"
bimap(
  p,
  (x) => x + 1,
  (s) => s.toUpperCase()
); // [2, "HELLO"]
swap(p); // ["hello", 1]

Range

import { range, rangeToArray, rangeInclusive } from "@typesugar/std";

rangeToArray(range(1, 5)); // [1, 2, 3, 4]
rangeToArray(rangeInclusive(1, 5)); // [1, 2, 3, 4, 5]
rangeToArray(range(0, 10, 2)); // [0, 2, 4, 6, 8]

API Reference

Typeclasses

  • FlatMap<F> β€” Sequencing for type constructors (map, flatMap)
  • flatMapArray, flatMapPromise, flatMapIterable, flatMapAsyncIterable β€” Built-in instances
  • registerFlatMap(name, instance) β€” Register a custom FlatMap instance
  • getFlatMap(name) β€” Look up a FlatMap instance by name

Macros

  • let:/yield: β€” Sequential (monadic) do-notation with guards, fallbacks, and discard bindings
  • par:/yield: β€” Parallel (applicative) comprehensions with Promise.all / .map().ap()

Data Types

  • Pair<A, B>, Triple<A, B, C> β€” Tuple types with utilities
  • Range β€” Numeric ranges with iteration support

License

MIT