
LazyPromise
A lazy, cancelable async primitive for TypeScript with typed errors and dependency injection
Gallery
About LazyPromise
LazyPromise is an open-source TypeScript library for asynchronous work that should start only when something subscribes and should stop cleanly when it is no longer needed. It sits between a native Promise and an RxJS Observable. Like a promise, it settles once and offers a familiar set of mapping, catching, finalization, combination, and racing operations. Like an observable, it is lazy, can run again for each subscription, and returns a disposable subscription that tears down the work. The project presents this smaller model as an alternative for developers who want several ideas from Effect without adopting a broad effect system.
A LazyPromise is created with a callback that receives a sink for resolving or rejecting. That callback can return teardown logic, which the library runs at most once. Nothing happens until code subscribes, and disposing a subscription cancels the upstream LazyPromises from which it was derived. Each new subscription runs the constructor callback again, so the primitive doesn't cache or share a previous result by default. The implementation enforces single settlement, prevents values after disposal, runs teardown before delivery, and flattens a LazyPromise returned as a value. Notifications are synchronous unless the caller explicitly places work in a microtask. That behavior removes the automatic microtask hop of native promises, but it also means developers need to understand ordering when they mix LazyPromise with ordinary async code.
The everyday API deliberately mirrors native Promise concepts while using names that avoid JavaScript's special treatment of thenables. The main transformation method is map rather than then, alongside catch, finally, all, allKeyed, race, any, box, rejecting, and defer. A mapping callback that returns another LazyPromise is flattened automatically, so the library doesn't need separate map and flatMap methods. The pipe method accepts a function or a custom operator for teams that prefer a compositional style. Conversion helpers support interoperation with eager native promises, so an application doesn't have to replace every async boundary at once. The package runs in modern browsers and supports Node.js 20.16 or later within the 20 series and Node.js 22.3 or later, with a browser playground for trying the model before installation.
For longer workflows, fromGen provides generator syntax that plays the role of async and await. A generator yields to a LazyPromise with yield*, then continues with normal JavaScript control flow when the value arrives. Cancellation propagates through chained operators and generator-based work. A cancellation while a generator is waiting doesn't run a finally block, which is an important distinction for cleanup code. The project also supports type-safe errors by wrapping expected failures in ErrorBox values. The catchBoxed operator handles them, while subscribe and conversion APIs produce type errors when boxed failures haven't been handled or explicitly allowed. Unexpected failures can still travel through the rejection channel, keeping routine domain outcomes distinct from bugs or exceptional conditions.
Dependency injection is carried by the LazyPromise type itself. A lazy callback can receive a dependency when it runs, and combinators merge the requirements of their inputs, so combining work that needs two services produces a value that requires both. The inject method can satisfy a dependency earlier, and the documentation suggests symbol-keyed objects when several modules share services. This is particularly useful in tests, where the same async workflow can receive production implementations or mocks without reaching into global state. It is a compact mechanism, but the extra type parameter and intersection types will feel most natural to teams already comfortable with advanced TypeScript.
LazyPromise fits browser interfaces, cancellable requests, event-driven application code, and libraries that need lazy async composition without bringing in a larger runtime. It is not a drop-in native Promise replacement. Its map naming, synchronous delivery, repeated execution per subscription, generator conventions, and explicit ErrorBox model all require deliberate adoption. Shared caching is intentionally left to userland state, and the library omits direct equivalents for some native helpers, including allSettled and withResolvers. The package is free under the MIT license, installs as @lazy-promise/core, and has no paid plan. Its focused documentation and StackBlitz playground make evaluation straightforward, while its young community and specialized semantics suggest introducing it first in a contained workflow.
Key Features
- Lazy cancelable async execution
- Promise-like composition operators
- Generator-based control flow
- Type-safe boxed errors
- Typed dependency injection
- Native Promise interoperation
Pros & Cons
What we like
- Starts work only when a subscriber needs it
- Cancellation propagates through derived operations
- Keeps the API smaller than a full effect system
- MIT license allows broad commercial use
Room for improvement
- Synchronous delivery needs careful ordering
- Not a drop-in replacement for native Promise
- Shared caching is left to userland
- Young library with a smaller community
Frequently Asked Questions
What is LazyPromise?
How is LazyPromise different from a native Promise?
Does LazyPromise support typed errors?
Is LazyPromise free?
Best For
Featured in
Alternatives to LazyPromise
Kevin Gabeci
Solo developer building web apps, cozy browser games, and AI creator toolkits.

SoloDevStack
A solo developer blog built on head-to-head tool comparisons, 580+ posts deep.

Codedex
A gamified, story-driven platform that teaches Python, web dev, and more like an RPG quest
Vibe Built
Building real apps with agentic AI. What worked, what broke, what shipped.
Reviews (0)
Badge builder
Add LazyPromise to your website
Choose a badge style and size, preview it here, then copy the generated HTML. Badge images are self-contained SVGs and do not require an external script.
<a href="https://toolindex.net/tools/lazypromise?ref=badge" target="_blank" rel="noopener">
<img src="https://toolindex.net/badge/lazypromise/medium.svg" alt="LazyPromise - Listed on Tool Index" width="180" height="50" />
</a> How to use the badge
- 1. Pick the style, size, and theme that fit your layout.
- 2. Copy the generated HTML from the code block.
- 3. Paste it into your footer, homepage, or press page.
Standard badge available
The standard listing badge is available now. Score and circle badges are limited to tools currently ranked in the top 10 of a category.
Badge clicks return visitors to this profile with a referral tag so the source remains identifiable.
Related Tools
Kevin Gabeci
Solo developer building web apps, cozy browser games, and AI creator toolkits.

Coolify
Self-hostable, open source alternative to Heroku and Netlify

Warp
The modern terminal reimagined with AI and collaboration

Bolt.new
Prompt-to-deployed full-stack app inside the browser
Work on LazyPromise? Request listing access or correction