better-effect

Introduction

A small, typed architecture for Result-based TypeScript applications.

Build applications around explicit dependencies

Most application code has two independent questions:

  1. Did this operation succeed?
  2. 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 failure

The complete path

define a Service

write an Effect.gen program

provide implementations with Layer

execute through Runtime

release resources through Scope

The 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.

On this page