Registry / http-networking / effect

effect

JSON →
library3.21.1jsnpmunverified

Effect-TS is a robust, type-safe functional programming library for TypeScript, providing a "missing standard library" for building highly concurrent, resilient, and performant applications. It centers around the `Effect` data type, which represents a description of a computation that may require resources (R), may fail with an error (E), and may succeed with a value (A). The library promotes a functional-first approach, emphasizing immutability, explicit error handling, and structured concurrency, leveraging TypeScript's type system to ensure correctness at compile-time. Currently stable at version 3.x (e.g., 3.21.1), `effect` maintains a regular release cadence with frequent patch and minor updates, reflecting active development and continuous improvement. It differentiates itself through its comprehensive ecosystem of modules (e.g., `Effect.Layer`, `Effect.Schema`, `Effect.Stream`) that integrate seamlessly, offering a complete solution for complex application logic, asynchronous operations, and resource management without runtime exceptions.

http-networkingweb-frameworkworkflowserializationdata
Install & Compatibility
Where this runs
tested against v? · npm install
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
node 18226 runs
build_error
glibc
node 18226 runs
build_error
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

Effect is the core data type representing a computation. The library is primarily ESM-first, especially in modern versions.

import { Effect } from 'effect'

Layer is used for dependency injection. In v3+, all core modules are exported from the single 'effect' package, consolidating imports.

import { Layer } from 'effect'

The `pipe` function is fundamental for functional composition. While `fp-ts` also uses `pipe`, `effect`'s version is integrated within its ecosystem. `pipe` is also often available as a method on `Effect` and other data types.

import { pipe } from 'effect'

Effect.gen uses generator functions with `yield*` for an imperative, async/await-like coding style, not regular async/await.

import { Effect } from 'effect'; const program = Effect.gen(function* () { /* ... */ });

This quickstart demonstrates creating and composing Effects, handling different types of errors with custom error classes, using `pipe` for composition, applying retry logic, and running the Effect to a Promise, including a simulated database defect.

import { Effect, Console, pipe, Duration, Schedule } from 'effect'; interface User { id: number; name: string; email: string; } // Define a custom error type for better type safety class UserNotFoundError extends Effect.Error('UserNotFoundError')<{ userId: number }> {} class DatabaseConnectionError extends Effect.Error('DatabaseConnectionError')<{ message: string }> {} // Simulate fetching a user from a database const fetchUserFromDB = (userId: number): Effect.Effect<User, UserNotFoundError | DatabaseConnectionError, never> => Effect.sync(() => { if (userId === 1) { return { id: 1, name: 'Alice', email: 'alice@example.com' }; } else if (userId === 99) { throw new Error('Failed to connect to DB'); // Simulate a defect } return Effect.fail(new UserNotFoundError({ userId })); }).pipe( Effect.catchAllDefect((error) => Effect.fail(new DatabaseConnectionError({ message: String(error) })) ) ); const program = pipe( fetchUserFromDB(1), // Try to fetch user with ID 1 Effect.tap((user) => Console.log(`Fetched user: ${user.name}`)), Effect.flatMap(() => fetchUserFromDB(2)), // Try to fetch user with ID 2 (will fail) Effect.tapError((error) => error._tag === 'UserNotFoundError' ? Console.error(`Error: User with ID ${error.userId} not found.`) : Console.error(`Critical Error: ${error.message}`) ), Effect.retry(Schedule.exponential(Duration.seconds(1), 3)), // Retry failed operations with exponential backoff Effect.matchEffect({ // Handle both success and failure paths explicitly onFailure: (error) => Console.error(`Final failure: ${error._tag}`), onSuccess: (user) => Console.log(`Final success (should not happen for user 2, unless retries succeed): ${user.name}`), }) ); // Run the Effect program Effect.runPromise(program).then(() => Console.log('Program finished.')).catch(console.error);
Debug
Known footguns
breakingMajor versions (e.g., v2 to v3) introduce significant breaking changes, including module reorganizations, API renames (e.g., `Either` to `Result`), and changes to `Layer` and `Service` definitions.
gotchaEffects are 'cold' and lazy; they describe a computation but do not execute until explicitly 'run' using functions like `Effect.runPromise`, `Effect.runSync`, or `Effect.runFork`. Forgetting to run an effect means its encapsulated logic (e.g., logging, side effects) will never occur.
gotchaUnderstanding the `Effect<A, E, R>` type parameters (Success, Error, Requirements) is crucial for type safety, especially 'R' (Requirements/Context). Incorrectly managing or providing dependencies (Services/Layers) can lead to compile-time type errors related to missing `R` or runtime failures if services are not provided.
gotchaWhen using `Effect.gen`, it's critical to use `yield*` (yield-star) for yielding other Effect values, not `await`. Using `await` directly within `Effect.gen` will often lead to unexpected behavior or type errors because it does not properly unwrap the Effect context.
gotchaA recently fixed defect in `RequestResolver.makeBatched` could cause consumer fibers to hang indefinitely if the resolver died with a defect, because cleanup logic was not correctly handling failures.
Upgrade
Version history

Breaking-change detection hasn't run for this library yet.

Audit
Security & dependencies

CVE tracking and dependency tree are planned for a later release.

Agent activity
13 hits · last 30 days
gptbot
4
ahrefsbot
4
script
1
Resources