TypeScript libraries

Small tools that make
illegal states unrepresentable.

A set of focused, aggressively type-safe libraries. Every doc page here is written and versioned inside the library's own repository — this site just knows where to look.

Get started

Buckets

Rules that read like sentences

Declare named conditions over an item once, then declare buckets as boolean expressions over those conditions. Condition names, bucket names and the shape of the report are all inferred.

  • Conditions are answered once per item, then reused by every bucket
  • Buckets are boolean expressions — AND, OR, NOT, ONLY
  • Bucket names and the shape of the report are inferred, not declared
Read the docs @michaelrwalker/buckets 17 pages
BucketEngine 3 conditions warehouse 0 digital 0 incomplete 0

Step Queue

Steps that resume exactly where they failed

Define BullMQ jobs as a set of fully type-safe steps. Job data accumulates as it moves through the pipeline, and a retried job resumes on the exact step it left off at.

  • Each step is typed against exactly what the steps before it produced
  • A retried job restarts on the step it failed on, not from the top
  • Wait on child jobs without hand-rolling WaitingChildrenError
Read the docs @michaelrwalker/step-queue 14 pages
1 fetchUser
2 chargeCard
3 sendReceipt
4 archive
job.data {}
status queued

Stagehand

A failed step rolls back everything that already succeeded

Scripts are phases, phases are steps. Steps have a handler and an optional rollback that fires when a later step fails, with a typed context threaded through the whole run.

  • A failing step rolls back every step that already succeeded
  • A typed context threads through the entire run
  • Live rendering on a TTY, plain line output in CI
Read the docs @michaelrwalker/stagehand 16 pages
deploy.ts

Braid

Joins that scale linearly not quadratically

Declare what each detail source is and how it joins. Braid indexes every source once into a Map and does a single lookup per row, so adding a fourth source costs one more pass instead of another scan per row.

  • Every source is indexed once, then one lookup per row — O(n + m), not O(n × m)
  • Each join widens the output row, so a duplicate name or mismatched key will not compile
  • Keys match the way a Map matches: no coercion, so "2" never silently joins 2
Read the docs @michaelrwalker/braid 16 pages
channel_one shopify variations products 3 rows
{ sku: "TS-100", channel_one : {…} , shopify : {…} , variations : [2] }
9 lookups vs 33 scans nested .find()