Introduction
A small, typed architecture for Result-based TypeScript applications.
Build applications around explicit dependencies
Most application code has two independent questions:
- Did this operation succeed?
- What does this operation need in order to run?
better-result answers the first
question with a typed Result. better-effect answers the second without
introducing a second error model, a fiber runtime, or a dependency container
that your application has to learn.
Effect.gen describes a Result workflow and its Service requirements
Layer describes how Services are provided
Runtime owns the environment and executes workflows
Scope owns resources and finalizers
better-result remains the source of truth for success and failureThe complete path
define a Service
↓
write an Effect.gen program
↓
provide implementations with Layer
↓
execute through Runtime
↓
release resources through ScopeThe library is intentionally small. It gives you a composition root and lifetime boundaries while leaving HTTP, queues, scheduling, persistence and dependency injection to ordinary TypeScript libraries or adapters.
Choose your starting point
Start with Getting Started, then read the Mental Model. You will build one Service, provide it through a Layer, and run it with a Runtime.
What this library is not
better-effect is not a reimplementation of Effect. It does not add fibers,
schedulers, streams, queues, a full Context abstraction, or a public
Effect<A, E, R> runtime type. An Effect program here is a
better-result Result (or Promise of one) carrying phantom Service metadata.
That smaller boundary is a feature: use the pieces when they solve a concrete problem and keep the rest of your application conventional.