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.
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
muslnode 18–226 runs
build_error
glibcnode 18–226 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);
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.