Skip to content

Creating Effects

Effect provides different ways to create effects, which are units of computation that encapsulate side effects. In this guide, we will cover some of the common methods that you can use to create effects.

In traditional programming, when an error occurs, it is often handled by throwing an exception:

// Type signature doesn't show possible exceptions
const
const divide: (a: number, b: number) => number
divide
= (
a: number
a
: number,
b: number
b
: number): number => {
if (
b: number
b
=== 0) {
throw new
var Error: ErrorConstructor
new (message?: string) => Error
Error
("Cannot divide by zero")
}
return
a: number
a
/
b: number
b
}

However, throwing errors can be problematic. The type signatures of functions do not indicate that they can throw exceptions, making it difficult to reason about potential errors.

To address this issue, Effect introduces dedicated constructors for creating effects that represent both success and failure: Effect.succeed and Effect.fail. These constructors allow you to explicitly handle success and failure cases while leveraging the type system to track errors.

Creates an Effect that always succeeds with a given value.

Use this function when you need an effect that completes successfully with a specific value without any errors or external dependencies.

Example (Creating a Successful Effect)

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
} from "effect"
// ┌─── Effect<number, never, never>
// ▼
const
const success: Effect.Effect<number, never, never>
success
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const succeed: <number>(value: number) => Effect.Effect<number, never, never>

Creates an Effect that always succeeds with a given value.

When to Use

Use this function when you need an effect that completes successfully with a specific value without any errors or external dependencies.

@seefail to create an effect that represents a failure.

@example

// Title: Creating a Successful Effect
import { Effect } from "effect"
// Creating an effect that represents a successful scenario
//
// ┌─── Effect<number, never, never>
// ▼
const success = Effect.succeed(42)

@since2.0.0

succeed
(42)

The type of success is Effect<number, never, never>, which means:

  • It produces a value of type number.
  • It does not generate any errors (never indicates no errors).
  • It requires no additional data or dependencies (never indicates no requirements).
┌─── Produces a value of type number
│ ┌─── Does not generate any errors
│ │ ┌─── Requires no dependencies
▼ ▼ ▼
Effect<number, never, never>

Creates an Effect that represents an error that can be recovered from.

Use this function to explicitly signal an error in an Effect. The error will keep propagating unless it is handled. You can handle the error with functions like Effect.catchAll or Effect.catchTag.

Example (Creating a Failed Effect)

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
} from "effect"
// ┌─── Effect<never, Error, never>
// ▼
const
const failure: Effect.Effect<never, Error, never>
failure
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const fail: <Error>(error: Error) => Effect.Effect<never, Error, never>

Creates an Effect that represents a recoverable error.

When to Use

Use this function to explicitly signal an error in an Effect. The error will keep propagating unless it is handled. You can handle the error with functions like

catchAll

or

catchTag

.

@seesucceed to create an effect that represents a successful value.

@example

// Title: Creating a Failed Effect
import { Effect } from "effect"
// ┌─── Effect<never, Error, never>
// ▼
const failure = Effect.fail(
new Error("Operation failed due to network error")
)

@since2.0.0

fail
(
new
var Error: ErrorConstructor
new (message?: string) => Error
Error
("Operation failed due to network error")
)

The type of failure is Effect<never, Error, never>, which means:

  • It never produces a value (never indicates that no successful result will be produced).
  • It fails with an error, specifically an Error.
  • It requires no additional data or dependencies (never indicates no requirements).
┌─── Never produces a value
│ ┌─── Fails with an Error
│ │ ┌─── Requires no dependencies
▼ ▼ ▼
Effect<never, Error, never>

Although you can use Error objects with Effect.fail, you can also pass strings, numbers, or more complex objects depending on your error management strategy.

Using “tagged” errors (objects with a _tag field) can help identify error types and works well with standard Effect functions, like Effect.catchTag.

Example (Using Tagged Errors)

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
} from "effect"
class
class HttpError
HttpError
{
readonly
HttpError._tag: "HttpError"
_tag
= "HttpError"
}
// ┌─── Effect<never, HttpError, never>
// ▼
const
const program: Effect.Effect<never, HttpError, never>
program
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const fail: <HttpError>(error: HttpError) => Effect.Effect<never, HttpError, never>

Creates an Effect that represents a recoverable error.

When to Use

Use this function to explicitly signal an error in an Effect. The error will keep propagating unless it is handled. You can handle the error with functions like

catchAll

or

catchTag

.

@seesucceed to create an effect that represents a successful value.

@example

// Title: Creating a Failed Effect
import { Effect } from "effect"
// ┌─── Effect<never, Error, never>
// ▼
const failure = Effect.fail(
new Error("Operation failed due to network error")
)

@since2.0.0

fail
(new
constructor HttpError(): HttpError
HttpError
())

With Effect.succeed and Effect.fail, you can explicitly handle success and failure cases and the type system will ensure that errors are tracked and accounted for.

Example (Rewriting a Division Function)

Here’s how you can rewrite the divide function using Effect, making error handling explicit.

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
} from "effect"
const
const divide: (a: number, b: number) => Effect.Effect<number, Error>
divide
= (
a: number
a
: number,
b: number
b
: number):
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
interface Effect<out A, out E = never, out R = never>

The Effect interface defines a value that lazily describes a workflow or job. The workflow requires some context R, and may fail with an error of type E, or succeed with a value of type A.

Effect values model resourceful interaction with the outside world, including synchronous, asynchronous, concurrent, and parallel interaction. They use a fiber-based concurrency model, with built-in support for scheduling, fine-grained interruption, structured concurrency, and high scalability.

To run an Effect value, you need a Runtime, which is a type that is capable of executing Effect values.

@since2.0.0

@since2.0.0

Effect
<number,
interface Error
Error
> =>
b: number
b
=== 0
?
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const fail: <Error>(error: Error) => Effect.Effect<never, Error, never>

Creates an Effect that represents a recoverable error.

When to Use

Use this function to explicitly signal an error in an Effect. The error will keep propagating unless it is handled. You can handle the error with functions like

catchAll

or

catchTag

.

@seesucceed to create an effect that represents a successful value.

@example

// Title: Creating a Failed Effect
import { Effect } from "effect"
// ┌─── Effect<never, Error, never>
// ▼
const failure = Effect.fail(
new Error("Operation failed due to network error")
)

@since2.0.0

fail
(new
var Error: ErrorConstructor
new (message?: string) => Error
Error
("Cannot divide by zero"))
:
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const succeed: <number>(value: number) => Effect.Effect<number, never, never>

Creates an Effect that always succeeds with a given value.

When to Use

Use this function when you need an effect that completes successfully with a specific value without any errors or external dependencies.

@seefail to create an effect that represents a failure.

@example

// Title: Creating a Successful Effect
import { Effect } from "effect"
// Creating an effect that represents a successful scenario
//
// ┌─── Effect<number, never, never>
// ▼
const success = Effect.succeed(42)

@since2.0.0

succeed
(
a: number
a
/
b: number
b
)

In this example, the divide function indicates in its return type Effect<number, Error> that the operation can either succeed with a number or fail with an Error.

┌─── Produces a value of type number
│ ┌─── Fails with an Error
▼ ▼
Effect<number, Error>

This clear type signature helps ensure that errors are handled properly and that anyone calling the function is aware of the possible outcomes.

Example (Simulating a User Retrieval Operation)

Let’s imagine another scenario where we use Effect.succeed and Effect.fail to model a simple user retrieval operation where the user data is hardcoded, which could be useful in testing scenarios or when mocking data:

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
} from "effect"
// Define a User type
interface
interface User
User
{
readonly
User.id: number
id
: number
readonly
User.name: string
name
: string
}
// A mocked function to simulate fetching a user from a database
const
const getUser: (userId: number) => Effect.Effect<User, Error>
getUser
= (
userId: number
userId
: number):
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
interface Effect<out A, out E = never, out R = never>

The Effect interface defines a value that lazily describes a workflow or job. The workflow requires some context R, and may fail with an error of type E, or succeed with a value of type A.

Effect values model resourceful interaction with the outside world, including synchronous, asynchronous, concurrent, and parallel interaction. They use a fiber-based concurrency model, with built-in support for scheduling, fine-grained interruption, structured concurrency, and high scalability.

To run an Effect value, you need a Runtime, which is a type that is capable of executing Effect values.

@since2.0.0

@since2.0.0

Effect
<
interface User
User
,
interface Error
Error
> => {
// Normally, you would access a database or API here, but we'll mock it
const
const userDatabase: Record<number, User>
userDatabase
:
type Record<K extends keyof any, T> = { [P in K]: T; }

Construct a type with a set of properties K of type T

Record
<number,
interface User
User
> = {
1: {
User.id: number
id
: 1,
User.name: string
name
: "John Doe" },
2: {
User.id: number
id
: 2,
User.name: string
name
: "Jane Smith" }
}
// Check if the user exists in our "database" and return appropriately
const
const user: User
user
=
const userDatabase: Record<number, User>
userDatabase
[
userId: number
userId
]
if (
const user: User
user
) {
return
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const succeed: <User>(value: User) => Effect.Effect<User, never, never>

Creates an Effect that always succeeds with a given value.

When to Use

Use this function when you need an effect that completes successfully with a specific value without any errors or external dependencies.

@seefail to create an effect that represents a failure.

@example

// Title: Creating a Successful Effect
import { Effect } from "effect"
// Creating an effect that represents a successful scenario
//
// ┌─── Effect<number, never, never>
// ▼
const success = Effect.succeed(42)

@since2.0.0

succeed
(
const user: User
user
)
} else {
return
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const fail: <Error>(error: Error) => Effect.Effect<never, Error, never>

Creates an Effect that represents a recoverable error.

When to Use

Use this function to explicitly signal an error in an Effect. The error will keep propagating unless it is handled. You can handle the error with functions like

catchAll

or

catchTag

.

@seesucceed to create an effect that represents a successful value.

@example

// Title: Creating a Failed Effect
import { Effect } from "effect"
// ┌─── Effect<never, Error, never>
// ▼
const failure = Effect.fail(
new Error("Operation failed due to network error")
)

@since2.0.0

fail
(new
var Error: ErrorConstructor
new (message?: string) => Error
Error
("User not found"))
}
}
// When executed, this will successfully return the user with id 1
const
const exampleUserEffect: Effect.Effect<User, Error, never>
exampleUserEffect
=
const getUser: (userId: number) => Effect.Effect<User, Error>
getUser
(1)

In this example, exampleUserEffect, which has the type Effect<User, Error>, will either produce a User object or an Error, depending on whether the user exists in the mocked database.

For a deeper dive into managing errors in your applications, refer to the Error Management Guide.

In JavaScript, you can delay the execution of synchronous computations using “thunks”.

Thunks are useful for delaying the computation of a value until it is needed.

To model synchronous side effects, Effect provides the Effect.sync and Effect.try constructors, which accept a thunk.

Creates an Effect that represents a synchronous side-effectful computation.

Use Effect.sync when you are sure the operation will not fail.

The provided function (thunk) must not throw errors; if it does, the error will be treated as a “defect”.

This defect is not a standard error but indicates a flaw in the logic that was expected to be error-free. You can think of it similar to an unexpected crash in the program, which can be further managed or logged using tools like Effect.catchAllDefect. This feature ensures that even unexpected failures in your application are not lost and can be handled appropriately.

Example (Logging a Message)

In the example below, Effect.sync is used to defer the side-effect of writing to the console.

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
} from "effect"
const
const log: (message: string) => Effect.Effect<void, never, never>
log
= (
message: string
message
: string) =>
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const sync: <void>(thunk: LazyArg<void>) => Effect.Effect<void, never, never>

Creates an Effect that represents a synchronous side-effectful computation.

When to Use

Use sync when you are sure the operation will not fail.

Details

The provided function (thunk) must not throw errors; if it does, the error will be treated as a "defect".

This defect is not a standard error but indicates a flaw in the logic that was expected to be error-free. You can think of it similar to an unexpected crash in the program, which can be further managed or logged using tools like

catchAllDefect

.

@seetry_try for a version that can handle failures.

@example

// Title: Logging a Message
import { Effect } from "effect"
const log = (message: string) =>
Effect.sync(() => {
console.log(message) // side effect
})
// ┌─── Effect<void, never, never>
// ▼
const program = log("Hello, World!")

@since2.0.0

sync
(() => {
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
(
message: string
message
) // side effect
})
// ┌─── Effect<void, never, never>
// ▼
const
const program: Effect.Effect<void, never, never>
program
=
const log: (message: string) => Effect.Effect<void, never, never>
log
("Hello, World!")

The side effect (logging to the console) encapsulated within program won’t occur until the effect is explicitly run (see the Running Effects section for more details). This allows you to define side effects at one point in your code and control when they are activated, improving manageability and predictability of side effects in larger applications.

Creates an Effect that represents a synchronous computation that might fail.

In situations where you need to perform synchronous operations that might fail, such as parsing JSON, you can use the Effect.try constructor. This constructor is designed to handle operations that could throw exceptions by capturing those exceptions and transforming them into manageable errors.

Example (Safe JSON Parsing)

Suppose you have a function that attempts to parse a JSON string. This operation can fail and throw an error if the input string is not properly formatted as JSON:

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
} from "effect"
const
const parse: (input: string) => Effect.Effect<any, UnknownException, never>
parse
= (
input: string
input
: string) =>
// This might throw an error if input is not valid JSON
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
try<any>(thunk: LazyArg<any>): Effect.Effect<any, UnknownException, never> (+1 overload)
export try
try
(() =>
var JSON: JSON

An intrinsic object that provides functions to convert JavaScript values to and from the JavaScript Object Notation (JSON) format.

JSON
.
JSON.parse(text: string, reviver?: (this: any, key: string, value: any) => any): any

Converts a JavaScript Object Notation (JSON) string into an object.

@paramtext A valid JSON string.

@paramreviver A function that transforms the results. This function is called for each member of the object. If a member contains nested objects, the nested objects are transformed before the parent object is.

parse
(
input: string
input
))
// ┌─── Effect<any, UnknownException, never>
// ▼
const
const program: Effect.Effect<any, UnknownException, never>
program
=
const parse: (input: string) => Effect.Effect<any, UnknownException, never>
parse
("")

In this example:

  • parse is a function that creates an effect encapsulating the JSON parsing operation.
  • If JSON.parse(input) throws an error due to invalid input, Effect.try catches this error and the effect represented by program will fail with an UnknownException. This ensures that errors are not silently ignored but are instead handled within the structured flow of effects.

You might want to transform the caught exception into a more specific error or perform additional operations when catching an error. Effect.try supports an overload that allows you to specify how caught exceptions should be transformed:

Example (Custom Error Handling)

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
} from "effect"
const
const parse: (input: string) => Effect.Effect<any, Error, never>
parse
= (
input: string
input
: string) =>
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
try<any, Error>(options: {
readonly try: LazyArg<any>;
readonly catch: (error: unknown) => Error;
}): Effect.Effect<any, Error, never> (+1 overload)
export try
try
({
// JSON.parse may throw for bad input
try: LazyArg<any>
try
: () =>
var JSON: JSON

An intrinsic object that provides functions to convert JavaScript values to and from the JavaScript Object Notation (JSON) format.

JSON
.
JSON.parse(text: string, reviver?: (this: any, key: string, value: any) => any): any

Converts a JavaScript Object Notation (JSON) string into an object.

@paramtext A valid JSON string.

@paramreviver A function that transforms the results. This function is called for each member of the object. If a member contains nested objects, the nested objects are transformed before the parent object is.

parse
(
input: string
input
),
// remap the error
catch: (error: unknown) => Error
catch
: (
unknown: unknown
unknown
) => new
var Error: ErrorConstructor
new (message?: string) => Error
Error
(`something went wrong ${
unknown: unknown
unknown
}`)
})
// ┌─── Effect<any, Error, never>
// ▼
const
const program: Effect.Effect<any, Error, never>
program
=
const parse: (input: string) => Effect.Effect<any, Error, never>
parse
("")

You can think of this as a similar pattern to the traditional try-catch block in JavaScript:

try {
return JSON.parse(input)
} catch (unknown) {
throw new Error(`something went wrong ${unknown}`)
}

In traditional programming, we often use Promises to handle asynchronous computations. However, dealing with errors in promises can be problematic. By default, Promise<Value> only provides the type Value for the resolved value, which means errors are not reflected in the type system. This limits the expressiveness and makes it challenging to handle and track errors effectively.

To overcome these limitations, Effect introduces dedicated constructors for creating effects that represent both success and failure in an asynchronous context: Effect.promise and Effect.tryPromise. These constructors allow you to explicitly handle success and failure cases while leveraging the type system to track errors.

Creates an Effect that represents an asynchronous computation guaranteed to succeed.

Use Effect.promise when you are sure the operation will not reject.

The provided function (thunk) returns a Promise that should never reject; if it does, the error will be treated as a “defect”.

This defect is not a standard error but indicates a flaw in the logic that was expected to be error-free. You can think of it similar to an unexpected crash in the program, which can be further managed or logged using tools like Effect.catchAllDefect. This feature ensures that even unexpected failures in your application are not lost and can be handled appropriately.

Example (Delayed Message)

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
} from "effect"
const
const delay: (message: string) => Effect.Effect<string, never, never>
delay
= (
message: string
message
: string) =>
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const promise: <string>(evaluate: (signal: AbortSignal) => PromiseLike<string>) => Effect.Effect<string, never, never>

Creates an Effect that represents an asynchronous computation guaranteed to succeed.

When to Use

Use promise when you are sure the operation will not reject.

Details

The provided function (thunk) returns a Promise that should never reject; if it does, the error will be treated as a "defect".

This defect is not a standard error but indicates a flaw in the logic that was expected to be error-free. You can think of it similar to an unexpected crash in the program, which can be further managed or logged using tools like

catchAllDefect

.

Interruptions

An optional AbortSignal can be provided to allow for interruption of the wrapped Promise API.

@seetryPromise for a version that can handle failures.

@example

// Title: Delayed Message
import { Effect } from "effect"
const delay = (message: string) =>
Effect.promise<string>(
() =>
new Promise((resolve) => {
setTimeout(() => {
resolve(message)
}, 2000)
})
)
// ┌─── Effect<string, never, never>
// ▼
const program = delay("Async operation completed successfully!")

@since2.0.0

promise
<string>(
() =>
new
var Promise: PromiseConstructor
new <string>(executor: (resolve: (value: string | PromiseLike<string>) => void, reject: (reason?: any) => void) => void) => Promise<string>

Creates a new Promise.

@paramexecutor A callback used to initialize the promise. This callback is passed two arguments: a resolve callback used to resolve the promise with a value or the result of another promise, and a reject callback used to reject the promise with a provided reason or error.

Promise
((
resolve: (value: string | PromiseLike<string>) => void
resolve
) => {
function setTimeout<[]>(callback: () => void, ms?: number): NodeJS.Timeout (+1 overload)

Schedules execution of a one-time callback after delay milliseconds.

The callback will likely not be invoked in precisely delay milliseconds. Node.js makes no guarantees about the exact timing of when callbacks will fire, nor of their ordering. The callback will be called as close as possible to the time specified.

When delay is larger than 2147483647 or less than 1, the delay will be set to 1. Non-integer delays are truncated to an integer.

If callback is not a function, a TypeError will be thrown.

This method has a custom variant for promises that is available using timersPromises.setTimeout().

@sincev0.0.1

@paramcallback The function to call when the timer elapses.

@paramdelay The number of milliseconds to wait before calling the callback.

@paramargs Optional arguments to pass when the callback is called.

setTimeout
(() => {
resolve: (value: string | PromiseLike<string>) => void
resolve
(
message: string
message
)
}, 2000)
})
)
// ┌─── Effect<string, never, never>
// ▼
const
const program: Effect.Effect<string, never, never>
program
=
const delay: (message: string) => Effect.Effect<string, never, never>
delay
("Async operation completed successfully!")

The program value has the type Effect<string, never, never> and can be interpreted as an effect that:

  • succeeds with a value of type string
  • does not produce any expected error (never)
  • does not require any context (never)

Creates an Effect that represents an asynchronous computation that might fail.

Unlike Effect.promise, this constructor is suitable when the underlying Promise might reject. It provides a way to catch errors and handle them appropriately. By default if an error occurs, it will be caught and propagated to the error channel as as an UnknownException.

Example (Fetching a TODO Item)

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
} from "effect"
const
const getTodo: (id: number) => Effect.Effect<Response, UnknownException, never>
getTodo
= (
id: number
id
: number) =>
// Will catch any errors and propagate them as UnknownException
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const tryPromise: <Response>(evaluate: (signal: AbortSignal) => PromiseLike<Response>) => Effect.Effect<Response, UnknownException, never> (+1 overload)

Creates an Effect that represents an asynchronous computation that might fail.

When to Use

In situations where you need to perform asynchronous operations that might fail, such as fetching data from an API, you can use the tryPromise constructor. This constructor is designed to handle operations that could throw exceptions by capturing those exceptions and transforming them into manageable errors.

Error Handling

There are two ways to handle errors with tryPromise:

  1. If you don't provide a catch function, the error is caught and the effect fails with an UnknownException.
  2. If you provide a catch function, the error is caught and the catch function maps it to an error of type E.

Interruptions

An optional AbortSignal can be provided to allow for interruption of the wrapped Promise API.

@seepromise if the effectful computation is asynchronous and does not throw errors.

@example

// Title: Fetching a TODO Item
import { Effect } from "effect"
const getTodo = (id: number) =>
// Will catch any errors and propagate them as UnknownException
Effect.tryPromise(() =>
fetch(`https://jsonplaceholder.typicode.com/todos/${id}`)
)
// ┌─── Effect<Response, UnknownException, never>
// ▼
const program = getTodo(1)

@example

// Title: Custom Error Handling import { Effect } from "effect"

const getTodo = (id: number) => Effect.tryPromise({ try: () => fetch(https://jsonplaceholder.typicode.com/todos/${id}), // remap the error catch: (unknown) => new Error(something went wrong ${unknown}) })

// ┌─── Effect<Response, Error, never> // ▼ const program = getTodo(1)

@since2.0.0

tryPromise
(() =>
function fetch(input: string | URL | globalThis.Request, init?: RequestInit): Promise<Response>
fetch
(`https://jsonplaceholder.typicode.com/todos/${
id: number
id
}`)
)
// ┌─── Effect<Response, UnknownException, never>
// ▼
const
const program: Effect.Effect<Response, UnknownException, never>
program
=
const getTodo: (id: number) => Effect.Effect<Response, UnknownException, never>
getTodo
(1)

The program value has the type Effect<Response, UnknownException, never> and can be interpreted as an effect that:

  • succeeds with a value of type Response
  • might produce an error (UnknownException)
  • does not require any context (never)

If you want more control over what gets propagated to the error channel, you can use an overload of Effect.tryPromise that takes a remapping function:

Example (Custom Error Handling)

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
} from "effect"
const
const getTodo: (id: number) => Effect.Effect<Response, Error, never>
getTodo
= (
id: number
id
: number) =>
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const tryPromise: <Response, Error>(options: {
readonly try: (signal: AbortSignal) => PromiseLike<Response>;
readonly catch: (error: unknown) => Error;
}) => Effect.Effect<...> (+1 overload)

Creates an Effect that represents an asynchronous computation that might fail.

When to Use

In situations where you need to perform asynchronous operations that might fail, such as fetching data from an API, you can use the tryPromise constructor. This constructor is designed to handle operations that could throw exceptions by capturing those exceptions and transforming them into manageable errors.

Error Handling

There are two ways to handle errors with tryPromise:

  1. If you don't provide a catch function, the error is caught and the effect fails with an UnknownException.
  2. If you provide a catch function, the error is caught and the catch function maps it to an error of type E.

Interruptions

An optional AbortSignal can be provided to allow for interruption of the wrapped Promise API.

@seepromise if the effectful computation is asynchronous and does not throw errors.

@example

// Title: Fetching a TODO Item
import { Effect } from "effect"
const getTodo = (id: number) =>
// Will catch any errors and propagate them as UnknownException
Effect.tryPromise(() =>
fetch(`https://jsonplaceholder.typicode.com/todos/${id}`)
)
// ┌─── Effect<Response, UnknownException, never>
// ▼
const program = getTodo(1)

@example

// Title: Custom Error Handling import { Effect } from "effect"

const getTodo = (id: number) => Effect.tryPromise({ try: () => fetch(https://jsonplaceholder.typicode.com/todos/${id}), // remap the error catch: (unknown) => new Error(something went wrong ${unknown}) })

// ┌─── Effect<Response, Error, never> // ▼ const program = getTodo(1)

@since2.0.0

tryPromise
({
try: (signal: AbortSignal) => PromiseLike<Response>
try
: () =>
function fetch(input: string | URL | globalThis.Request, init?: RequestInit): Promise<Response>
fetch
(`https://jsonplaceholder.typicode.com/todos/${
id: number
id
}`),
// remap the error
catch: (error: unknown) => Error
catch
: (
unknown: unknown
unknown
) => new
var Error: ErrorConstructor
new (message?: string) => Error
Error
(`something went wrong ${
unknown: unknown
unknown
}`)
})
// ┌─── Effect<Response, Error, never>
// ▼
const
const program: Effect.Effect<Response, Error, never>
program
=
const getTodo: (id: number) => Effect.Effect<Response, Error, never>
getTodo
(1)

Creates an Effect from a callback-based asynchronous function.

Sometimes you have to work with APIs that don’t support async/await or Promise and instead use the callback style. To handle callback-based APIs, Effect provides the Effect.async constructor.

Example (Wrapping a Callback API)

Let’s wrap the readFile function from Node.js’s fs module into an Effect-based API (make sure @types/node is installed):

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
} from "effect"
import * as
module "node:fs"
NodeFS
from "node:fs"
const
const readFile: (filename: string) => Effect.Effect<Buffer<ArrayBufferLike>, Error, never>
readFile
= (
filename: string
filename
: string) =>
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const async: <Buffer<ArrayBufferLike>, Error, never>(resume: (callback: (_: Effect.Effect<Buffer<ArrayBufferLike>, Error, never>) => void, signal: AbortSignal) => void | Effect.Effect<...>, blockingOn?: FiberId) => Effect.Effect<...>

Creates an Effect from a callback-based asynchronous function.

When to Use

Use async when dealing with APIs that use callback-style instead of async/await or Promise.

Details

The resume function:

  • Must be called exactly once. Any additional calls will be ignored.
  • Can return an optional Effect that will be run if the Fiber executing this Effect is interrupted. This can be useful in scenarios where you need to handle resource cleanup if the operation is interrupted.
  • Can receive an AbortSignal to handle interruption if needed.

The FiberId of the fiber that may complete the async callback may also be specified using the blockingOn argument. This is called the "blocking fiber" because it suspends the fiber executing the async effect (i.e. semantically blocks the fiber from making progress). Specifying this fiber id in cases where it is known will improve diagnostics, but not affect the behavior of the returned effect.

@example

// Title: Wrapping a Callback API
import { Effect } from "effect"
import * as NodeFS from "node:fs"
const readFile = (filename: string) =>
Effect.async<Buffer, Error>((resume) => {
NodeFS.readFile(filename, (error, data) => {
if (error) {
// Resume with a failed Effect if an error occurs
resume(Effect.fail(error))
} else {
// Resume with a succeeded Effect if successful
resume(Effect.succeed(data))
}
})
})
// ┌─── Effect<Buffer, Error, never>
// ▼
const program = readFile("example.txt")

@example

// Title: Handling Interruption with Cleanup import { Effect, Fiber } from "effect" import * as NodeFS from "node:fs"

// Simulates a long-running operation to write to a file const writeFileWithCleanup = (filename: string, data: string) => Effect.async<void, Error>((resume) => { const writeStream = NodeFS.createWriteStream(filename)

// Start writing data to the file
writeStream.write(data)
// When the stream is finished, resume with success
writeStream.on("finish", () => resume(Effect.void))
// In case of an error during writing, resume with failure
writeStream.on("error", (err) => resume(Effect.fail(err)))
// Handle interruption by returning a cleanup effect
return Effect.sync(() => {
console.log(`Cleaning up ${filename}`)
NodeFS.unlinkSync(filename)
})

})

const program = Effect.gen(function* () { const fiber = yield* Effect.fork( writeFileWithCleanup("example.txt", "Some long data...") ) // Simulate interrupting the fiber after 1 second yield* Effect.sleep("1 second") yield* Fiber.interrupt(fiber) // This will trigger the cleanup })

// Run the program Effect.runPromise(program) // Output: // Cleaning up example.txt

@example

// Title: Handling Interruption with AbortSignal import { Effect, Fiber } from "effect"

// A task that supports interruption using AbortSignal const interruptibleTask = Effect.async<void, Error>((resume, signal) => { // Handle interruption signal.addEventListener("abort", () => { console.log("Abort signal received") clearTimeout(timeoutId) })

// Simulate a long-running task const timeoutId = setTimeout(() => { console.log("Operation completed") resume(Effect.void) }, 2000) })

const program = Effect.gen(function* () { const fiber = yield* Effect.fork(interruptibleTask) // Simulate interrupting the fiber after 1 second yield* Effect.sleep("1 second") yield* Fiber.interrupt(fiber) })

// Run the program Effect.runPromise(program) // Output: // Abort signal received

@since2.0.0

async
<
interface Buffer<TArrayBuffer extends ArrayBufferLike = ArrayBufferLike>
Buffer
,
interface Error
Error
>((
resume: (_: Effect.Effect<Buffer<ArrayBufferLike>, Error, never>) => void
resume
) => {
module "node:fs"
NodeFS
.
function readFile(path: NodeFS.PathOrFileDescriptor, callback: (err: NodeJS.ErrnoException | null, data: Buffer) => void): void (+3 overloads)

Asynchronously reads the entire contents of a file.

@parampath A path to a file. If a URL is provided, it must use the file: protocol. If a file descriptor is provided, the underlying file will not be closed automatically.

readFile
(
filename: string
filename
, (
error: NodeJS.ErrnoException | null
error
,
data: Buffer<ArrayBufferLike>
data
) => {
if (
error: NodeJS.ErrnoException | null
error
) {
// Resume with a failed Effect if an error occurs
resume: (_: Effect.Effect<Buffer<ArrayBufferLike>, Error, never>) => void
resume
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const fail: <NodeJS.ErrnoException>(error: NodeJS.ErrnoException) => Effect.Effect<never, NodeJS.ErrnoException, never>

Creates an Effect that represents a recoverable error.

When to Use

Use this function to explicitly signal an error in an Effect. The error will keep propagating unless it is handled. You can handle the error with functions like

catchAll

or

catchTag

.

@seesucceed to create an effect that represents a successful value.

@example

// Title: Creating a Failed Effect
import { Effect } from "effect"
// ┌─── Effect<never, Error, never>
// ▼
const failure = Effect.fail(
new Error("Operation failed due to network error")
)

@since2.0.0

fail
(
error: NodeJS.ErrnoException
error
))
} else {
// Resume with a succeeded Effect if successful
resume: (_: Effect.Effect<Buffer<ArrayBufferLike>, Error, never>) => void
resume
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const succeed: <Buffer<ArrayBufferLike>>(value: Buffer<ArrayBufferLike>) => Effect.Effect<Buffer<ArrayBufferLike>, never, never>

Creates an Effect that always succeeds with a given value.

When to Use

Use this function when you need an effect that completes successfully with a specific value without any errors or external dependencies.

@seefail to create an effect that represents a failure.

@example

// Title: Creating a Successful Effect
import { Effect } from "effect"
// Creating an effect that represents a successful scenario
//
// ┌─── Effect<number, never, never>
// ▼
const success = Effect.succeed(42)

@since2.0.0

succeed
(
data: Buffer<ArrayBufferLike>
data
))
}
})
})
// ┌─── Effect<Buffer, Error, never>
// ▼
const
const program: Effect.Effect<Buffer<ArrayBufferLike>, Error, never>
program
=
const readFile: (filename: string) => Effect.Effect<Buffer<ArrayBufferLike>, Error, never>
readFile
("example.txt")

In the above example, we manually annotate the types when calling Effect.async:

Effect.async<Buffer, Error>((resume) => {
// ...
})

because TypeScript cannot infer the type parameters for a callback based on the return value inside the callback body. Annotating the types ensures that the values provided to resume match the expected types.

The resume function inside Effect.async should be called exactly once. Calling it more than once will result in the extra calls being ignored.

Example (Ignoring Subsequent resume Calls)

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
} from "effect"
const
const program: Effect.Effect<number, never, never>
program
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const async: <number, never, never>(resume: (callback: (_: Effect.Effect<number, never, never>) => void, signal: AbortSignal) => void | Effect.Effect<void, never, never>, blockingOn?: FiberId) => Effect.Effect<...>

Creates an Effect from a callback-based asynchronous function.

When to Use

Use async when dealing with APIs that use callback-style instead of async/await or Promise.

Details

The resume function:

  • Must be called exactly once. Any additional calls will be ignored.
  • Can return an optional Effect that will be run if the Fiber executing this Effect is interrupted. This can be useful in scenarios where you need to handle resource cleanup if the operation is interrupted.
  • Can receive an AbortSignal to handle interruption if needed.

The FiberId of the fiber that may complete the async callback may also be specified using the blockingOn argument. This is called the "blocking fiber" because it suspends the fiber executing the async effect (i.e. semantically blocks the fiber from making progress). Specifying this fiber id in cases where it is known will improve diagnostics, but not affect the behavior of the returned effect.

@example

// Title: Wrapping a Callback API
import { Effect } from "effect"
import * as NodeFS from "node:fs"
const readFile = (filename: string) =>
Effect.async<Buffer, Error>((resume) => {
NodeFS.readFile(filename, (error, data) => {
if (error) {
// Resume with a failed Effect if an error occurs
resume(Effect.fail(error))
} else {
// Resume with a succeeded Effect if successful
resume(Effect.succeed(data))
}
})
})
// ┌─── Effect<Buffer, Error, never>
// ▼
const program = readFile("example.txt")

@example

// Title: Handling Interruption with Cleanup import { Effect, Fiber } from "effect" import * as NodeFS from "node:fs"

// Simulates a long-running operation to write to a file const writeFileWithCleanup = (filename: string, data: string) => Effect.async<void, Error>((resume) => { const writeStream = NodeFS.createWriteStream(filename)

// Start writing data to the file
writeStream.write(data)
// When the stream is finished, resume with success
writeStream.on("finish", () => resume(Effect.void))
// In case of an error during writing, resume with failure
writeStream.on("error", (err) => resume(Effect.fail(err)))
// Handle interruption by returning a cleanup effect
return Effect.sync(() => {
console.log(`Cleaning up ${filename}`)
NodeFS.unlinkSync(filename)
})

})

const program = Effect.gen(function* () { const fiber = yield* Effect.fork( writeFileWithCleanup("example.txt", "Some long data...") ) // Simulate interrupting the fiber after 1 second yield* Effect.sleep("1 second") yield* Fiber.interrupt(fiber) // This will trigger the cleanup })

// Run the program Effect.runPromise(program) // Output: // Cleaning up example.txt

@example

// Title: Handling Interruption with AbortSignal import { Effect, Fiber } from "effect"

// A task that supports interruption using AbortSignal const interruptibleTask = Effect.async<void, Error>((resume, signal) => { // Handle interruption signal.addEventListener("abort", () => { console.log("Abort signal received") clearTimeout(timeoutId) })

// Simulate a long-running task const timeoutId = setTimeout(() => { console.log("Operation completed") resume(Effect.void) }, 2000) })

const program = Effect.gen(function* () { const fiber = yield* Effect.fork(interruptibleTask) // Simulate interrupting the fiber after 1 second yield* Effect.sleep("1 second") yield* Fiber.interrupt(fiber) })

// Run the program Effect.runPromise(program) // Output: // Abort signal received

@since2.0.0

async
<number>((
resume: (_: Effect.Effect<number, never, never>) => void
resume
) => {
resume: (_: Effect.Effect<number, never, never>) => void
resume
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const succeed: <number>(value: number) => Effect.Effect<number, never, never>

Creates an Effect that always succeeds with a given value.

When to Use

Use this function when you need an effect that completes successfully with a specific value without any errors or external dependencies.

@seefail to create an effect that represents a failure.

@example

// Title: Creating a Successful Effect
import { Effect } from "effect"
// Creating an effect that represents a successful scenario
//
// ┌─── Effect<number, never, never>
// ▼
const success = Effect.succeed(42)

@since2.0.0

succeed
(1))
resume: (_: Effect.Effect<number, never, never>) => void
resume
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const succeed: <number>(value: number) => Effect.Effect<number, never, never>

Creates an Effect that always succeeds with a given value.

When to Use

Use this function when you need an effect that completes successfully with a specific value without any errors or external dependencies.

@seefail to create an effect that represents a failure.

@example

// Title: Creating a Successful Effect
import { Effect } from "effect"
// Creating an effect that represents a successful scenario
//
// ┌─── Effect<number, never, never>
// ▼
const success = Effect.succeed(42)

@since2.0.0

succeed
(2)) // This line will be ignored
})
// Run the program
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const runPromise: <number, never>(effect: Effect.Effect<number, never, never>, options?: {
readonly signal?: AbortSignal;
} | undefined) => Promise<number>

Executes an effect and returns the result as a Promise.

When to Use

Use runPromise when you need to execute an effect and work with the result using Promise syntax, typically for compatibility with other promise-based code.

If the effect succeeds, the promise will resolve with the result. If the effect fails, the promise will reject with an error.

@seerunPromiseExit for a version that returns an Exit type instead of rejecting.

@example

// Title: Running a Successful Effect as a Promise
import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

@example

//Example: Handling a Failing Effect as a Rejected Promise import { Effect } from "effect"

Effect.runPromise(Effect.fail("my error")).catch(console.error) // Output: // (FiberFailure) Error: my error

@since2.0.0

runPromise
(
const program: Effect.Effect<number, never, never>
program
).
Promise<number>.then<void, never>(onfulfilled?: ((value: number) => void | PromiseLike<void>) | null | undefined, onrejected?: ((reason: any) => PromiseLike<never>) | null | undefined): Promise<...>

Attaches callbacks for the resolution and/or rejection of the Promise.

@paramonfulfilled The callback to execute when the Promise is resolved.

@paramonrejected The callback to execute when the Promise is rejected.

@returnsA Promise for the completion of which ever callback is executed.

then
(
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
) // Output: 1

For more advanced use cases, resume can optionally return an Effect that will be executed if the fiber running this effect is interrupted. This can be useful in scenarios where you need to handle resource cleanup if the operation is interrupted.

Example (Handling Interruption with Cleanup)

In this example:

  • The writeFileWithCleanup function writes data to a file.
  • If the fiber running this effect is interrupted, the cleanup effect (which deletes the file) is executed.
  • This ensures that resources like open file handles are cleaned up properly when the operation is canceled.
import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
,
import Fiber
Fiber
} from "effect"
import * as
module "node:fs"
NodeFS
from "node:fs"
// Simulates a long-running operation to write to a file
const
const writeFileWithCleanup: (filename: string, data: string) => Effect.Effect<void, Error, never>
writeFileWithCleanup
= (
filename: string
filename
: string,
data: string
data
: string) =>
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const async: <void, Error, never>(resume: (callback: (_: Effect.Effect<void, Error, never>) => void, signal: AbortSignal) => void | Effect.Effect<void, never, never>, blockingOn?: FiberId) => Effect.Effect<...>

Creates an Effect from a callback-based asynchronous function.

When to Use

Use async when dealing with APIs that use callback-style instead of async/await or Promise.

Details

The resume function:

  • Must be called exactly once. Any additional calls will be ignored.
  • Can return an optional Effect that will be run if the Fiber executing this Effect is interrupted. This can be useful in scenarios where you need to handle resource cleanup if the operation is interrupted.
  • Can receive an AbortSignal to handle interruption if needed.

The FiberId of the fiber that may complete the async callback may also be specified using the blockingOn argument. This is called the "blocking fiber" because it suspends the fiber executing the async effect (i.e. semantically blocks the fiber from making progress). Specifying this fiber id in cases where it is known will improve diagnostics, but not affect the behavior of the returned effect.

@example

// Title: Wrapping a Callback API
import { Effect } from "effect"
import * as NodeFS from "node:fs"
const readFile = (filename: string) =>
Effect.async<Buffer, Error>((resume) => {
NodeFS.readFile(filename, (error, data) => {
if (error) {
// Resume with a failed Effect if an error occurs
resume(Effect.fail(error))
} else {
// Resume with a succeeded Effect if successful
resume(Effect.succeed(data))
}
})
})
// ┌─── Effect<Buffer, Error, never>
// ▼
const program = readFile("example.txt")

@example

// Title: Handling Interruption with Cleanup import { Effect, Fiber } from "effect" import * as NodeFS from "node:fs"

// Simulates a long-running operation to write to a file const writeFileWithCleanup = (filename: string, data: string) => Effect.async<void, Error>((resume) => { const writeStream = NodeFS.createWriteStream(filename)

// Start writing data to the file
writeStream.write(data)
// When the stream is finished, resume with success
writeStream.on("finish", () => resume(Effect.void))
// In case of an error during writing, resume with failure
writeStream.on("error", (err) => resume(Effect.fail(err)))
// Handle interruption by returning a cleanup effect
return Effect.sync(() => {
console.log(`Cleaning up ${filename}`)
NodeFS.unlinkSync(filename)
})

})

const program = Effect.gen(function* () { const fiber = yield* Effect.fork( writeFileWithCleanup("example.txt", "Some long data...") ) // Simulate interrupting the fiber after 1 second yield* Effect.sleep("1 second") yield* Fiber.interrupt(fiber) // This will trigger the cleanup })

// Run the program Effect.runPromise(program) // Output: // Cleaning up example.txt

@example

// Title: Handling Interruption with AbortSignal import { Effect, Fiber } from "effect"

// A task that supports interruption using AbortSignal const interruptibleTask = Effect.async<void, Error>((resume, signal) => { // Handle interruption signal.addEventListener("abort", () => { console.log("Abort signal received") clearTimeout(timeoutId) })

// Simulate a long-running task const timeoutId = setTimeout(() => { console.log("Operation completed") resume(Effect.void) }, 2000) })

const program = Effect.gen(function* () { const fiber = yield* Effect.fork(interruptibleTask) // Simulate interrupting the fiber after 1 second yield* Effect.sleep("1 second") yield* Fiber.interrupt(fiber) })

// Run the program Effect.runPromise(program) // Output: // Abort signal received

@since2.0.0

async
<void,
interface Error
Error
>((
resume: (_: Effect.Effect<void, Error, never>) => void
resume
) => {
const
const writeStream: NodeFS.WriteStream
writeStream
=
module "node:fs"
NodeFS
.
function createWriteStream(path: NodeFS.PathLike, options?: BufferEncoding | WriteStreamOptions): NodeFS.WriteStream

options may also include a start option to allow writing data at some position past the beginning of the file, allowed values are in the [0, Number.MAX_SAFE_INTEGER] range. Modifying a file rather than replacing it may require the flags option to be set to r+ rather than the default w. The encoding can be any one of those accepted by Buffer.

If autoClose is set to true (default behavior) on 'error' or 'finish' the file descriptor will be closed automatically. If autoClose is false, then the file descriptor won't be closed, even if there's an error. It is the application's responsibility to close it and make sure there's no file descriptor leak.

By default, the stream will emit a 'close' event after it has been destroyed. Set the emitClose option to false to change this behavior.

By providing the fs option it is possible to override the corresponding fs implementations for open, write, writev, and close. Overriding write() without writev() can reduce performance as some optimizations (_writev()) will be disabled. When providing the fs option, overrides for at least one of write and writev are required. If no fd option is supplied, an override for open is also required. If autoClose is true, an override for close is also required.

Like fs.ReadStream, if fd is specified, fs.WriteStream will ignore the path argument and will use the specified file descriptor. This means that no 'open' event will be emitted. fd should be blocking; non-blocking fds should be passed to net.Socket.

If options is a string, then it specifies the encoding.

@sincev0.1.31

createWriteStream
(
filename: string
filename
)
// Start writing data to the file
const writeStream: NodeFS.WriteStream
writeStream
.
WritableBase.write(chunk: any, callback?: (error: Error | null | undefined) => void): boolean (+1 overload)

The writable.write() method writes some data to the stream, and calls the supplied callback once the data has been fully handled. If an error occurs, the callback will be called with the error as its first argument. The callback is called asynchronously and before 'error' is emitted.

The return value is true if the internal buffer is less than the highWaterMark configured when the stream was created after admitting chunk. If false is returned, further attempts to write data to the stream should stop until the 'drain' event is emitted.

While a stream is not draining, calls to write() will buffer chunk, and return false. Once all currently buffered chunks are drained (accepted for delivery by the operating system), the 'drain' event will be emitted. Once write() returns false, do not write more chunks until the 'drain' event is emitted. While calling write() on a stream that is not draining is allowed, Node.js will buffer all written chunks until maximum memory usage occurs, at which point it will abort unconditionally. Even before it aborts, high memory usage will cause poor garbage collector performance and high RSS (which is not typically released back to the system, even after the memory is no longer required). Since TCP sockets may never drain if the remote peer does not read the data, writing a socket that is not draining may lead to a remotely exploitable vulnerability.

Writing data while the stream is not draining is particularly problematic for a Transform, because the Transform streams are paused by default until they are piped or a 'data' or 'readable' event handler is added.

If the data to be written can be generated or fetched on demand, it is recommended to encapsulate the logic into a Readable and use

pipe

. However, if calling write() is preferred, it is possible to respect backpressure and avoid memory issues using the 'drain' event:

function write(data, cb) {
if (!stream.write(data)) {
stream.once('drain', cb);
} else {
process.nextTick(cb);
}
}
// Wait for cb to be called before doing any other write.
write('hello', () => {
console.log('Write completed, do more writes now.');
});

A Writable stream in object mode will always ignore the encoding argument.

@sincev0.9.4

@paramchunk Optional data to write. For streams not operating in object mode, chunk must be a {string}, {Buffer}, {TypedArray} or {DataView}. For object mode streams, chunk may be any JavaScript value other than null.

@paramencoding The encoding, if chunk is a string.

@paramcallback Callback for when this chunk of data is flushed.

write
(
data: string
data
)
// When the stream is finished, resume with success
const writeStream: NodeFS.WriteStream
writeStream
.
WriteStream.on(event: "finish", listener: () => void): NodeFS.WriteStream (+8 overloads)

Adds the listener function to the end of the listeners array for the event named eventName. No checks are made to see if the listener has already been added. Multiple calls passing the same combination of eventName and listener will result in the listener being added, and called, multiple times.

server.on('connection', (stream) => {
console.log('someone connected!');
});

Returns a reference to the EventEmitter, so that calls can be chained.

By default, event listeners are invoked in the order they are added. The emitter.prependListener() method can be used as an alternative to add the event listener to the beginning of the listeners array.

import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.on('foo', () => console.log('a'));
myEE.prependListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
// b
// a

on
("finish", () =>
resume: (_: Effect.Effect<void, Error, never>) => void
resume
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const void: Effect.Effect<void, never, never>
export void

@since2.0.0

void
))
// In case of an error during writing, resume with failure
const writeStream: NodeFS.WriteStream
writeStream
.
WriteStream.on(event: "error", listener: (err: Error) => void): NodeFS.WriteStream (+8 overloads)

Adds the listener function to the end of the listeners array for the event named eventName. No checks are made to see if the listener has already been added. Multiple calls passing the same combination of eventName and listener will result in the listener being added, and called, multiple times.

server.on('connection', (stream) => {
console.log('someone connected!');
});

Returns a reference to the EventEmitter, so that calls can be chained.

By default, event listeners are invoked in the order they are added. The emitter.prependListener() method can be used as an alternative to add the event listener to the beginning of the listeners array.

import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.on('foo', () => console.log('a'));
myEE.prependListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
// b
// a

on
("error", (
err: Error
err
) =>
resume: (_: Effect.Effect<void, Error, never>) => void
resume
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const fail: <Error>(error: Error) => Effect.Effect<never, Error, never>

Creates an Effect that represents a recoverable error.

When to Use

Use this function to explicitly signal an error in an Effect. The error will keep propagating unless it is handled. You can handle the error with functions like

catchAll

or

catchTag

.

@seesucceed to create an effect that represents a successful value.

@example

// Title: Creating a Failed Effect
import { Effect } from "effect"
// ┌─── Effect<never, Error, never>
// ▼
const failure = Effect.fail(
new Error("Operation failed due to network error")
)

@since2.0.0

fail
(
err: Error
err
)))
// Handle interruption by returning a cleanup effect
return
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const sync: <void>(thunk: LazyArg<void>) => Effect.Effect<void, never, never>

Creates an Effect that represents a synchronous side-effectful computation.

When to Use

Use sync when you are sure the operation will not fail.

Details

The provided function (thunk) must not throw errors; if it does, the error will be treated as a "defect".

This defect is not a standard error but indicates a flaw in the logic that was expected to be error-free. You can think of it similar to an unexpected crash in the program, which can be further managed or logged using tools like

catchAllDefect

.

@seetry_try for a version that can handle failures.

@example

// Title: Logging a Message
import { Effect } from "effect"
const log = (message: string) =>
Effect.sync(() => {
console.log(message) // side effect
})
// ┌─── Effect<void, never, never>
// ▼
const program = log("Hello, World!")

@since2.0.0

sync
(() => {
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
(`Cleaning up ${
filename: string
filename
}`)
module "node:fs"
NodeFS
.
function unlinkSync(path: NodeFS.PathLike): void

Synchronous unlink(2). Returns undefined.

@sincev0.1.21

unlinkSync
(
filename: string
filename
)
})
})
const
const program: Effect.Effect<void, never, never>
program
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, void, never>) => Effect.Effect<...> (+1 overload)

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to Use

gen allows you to write code that looks and behaves like synchronous code, but it can handle asynchronous tasks, errors, and complex control flow (like loops and conditions). It helps make asynchronous code more readable and easier to manage.

The generator functions work similarly to async/await but with more explicit control over the execution of effects. You can yield* values from effects and return the final result at the end.

@example

import { Effect } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function* () {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})

@since2.0.0

gen
(function* () {
const
const fiber: Fiber.RuntimeFiber<void, Error>
fiber
= yield*
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const fork: <void, Error, never>(self: Effect.Effect<void, Error, never>) => Effect.Effect<Fiber.RuntimeFiber<void, Error>, never, never>

Returns an effect that forks this effect into its own separate fiber, returning the fiber immediately, without waiting for it to begin executing the effect.

You can use the fork method whenever you want to execute an effect in a new fiber, concurrently and without "blocking" the fiber executing other effects. Using fibers can be tricky, so instead of using this method directly, consider other higher-level methods, such as raceWith, zipPar, and so forth.

The fiber returned by this method has methods to interrupt the fiber and to wait for it to finish executing the effect. See Fiber for more information.

Whenever you use this method to launch a new fiber, the new fiber is attached to the parent fiber's scope. This means when the parent fiber terminates, the child fiber will be terminated as well, ensuring that no fibers leak. This behavior is called "auto supervision", and if this behavior is not desired, you may use the forkDaemon or forkIn methods.

@since2.0.0

fork
(
const writeFileWithCleanup: (filename: string, data: string) => Effect.Effect<void, Error, never>
writeFileWithCleanup
("example.txt", "Some long data...")
)
// Simulate interrupting the fiber after 1 second
yield*
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const sleep: (duration: DurationInput) => Effect.Effect<void>

Returns an effect that suspends for the specified duration. This method is asynchronous, and does not actually block the fiber executing the effect.

@since2.0.0

sleep
("1 second")
yield*
import Fiber
Fiber
.
const interrupt: <void, Error>(self: Fiber.Fiber<void, Error>) => Effect.Effect<Exit<void, Error>, never, never>

Interrupts the fiber from whichever fiber is calling this method. If the fiber has already exited, the returned effect will resume immediately. Otherwise, the effect will resume when the fiber exits.

@since2.0.0

interrupt
(
const fiber: Fiber.RuntimeFiber<void, Error>
fiber
) // This will trigger the cleanup
})
// Run the program
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const runPromise: <void, never>(effect: Effect.Effect<void, never, never>, options?: {
readonly signal?: AbortSignal;
} | undefined) => Promise<void>

Executes an effect and returns the result as a Promise.

When to Use

Use runPromise when you need to execute an effect and work with the result using Promise syntax, typically for compatibility with other promise-based code.

If the effect succeeds, the promise will resolve with the result. If the effect fails, the promise will reject with an error.

@seerunPromiseExit for a version that returns an Exit type instead of rejecting.

@example

// Title: Running a Successful Effect as a Promise
import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

@example

//Example: Handling a Failing Effect as a Rejected Promise import { Effect } from "effect"

Effect.runPromise(Effect.fail("my error")).catch(console.error) // Output: // (FiberFailure) Error: my error

@since2.0.0

runPromise
(
const program: Effect.Effect<void, never, never>
program
)
/*
Output:
Cleaning up example.txt
*/

If the operation you’re wrapping supports interruption, the resume function can receive an AbortSignal to handle interruption requests directly.

Example (Handling Interruption with AbortSignal)

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
,
import Fiber
Fiber
} from "effect"
// A task that supports interruption using AbortSignal
const
const interruptibleTask: Effect.Effect<void, Error, never>
interruptibleTask
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const async: <void, Error, never>(resume: (callback: (_: Effect.Effect<void, Error, never>) => void, signal: AbortSignal) => void | Effect.Effect<void, never, never>, blockingOn?: FiberId) => Effect.Effect<...>

Creates an Effect from a callback-based asynchronous function.

When to Use

Use async when dealing with APIs that use callback-style instead of async/await or Promise.

Details

The resume function:

  • Must be called exactly once. Any additional calls will be ignored.
  • Can return an optional Effect that will be run if the Fiber executing this Effect is interrupted. This can be useful in scenarios where you need to handle resource cleanup if the operation is interrupted.
  • Can receive an AbortSignal to handle interruption if needed.

The FiberId of the fiber that may complete the async callback may also be specified using the blockingOn argument. This is called the "blocking fiber" because it suspends the fiber executing the async effect (i.e. semantically blocks the fiber from making progress). Specifying this fiber id in cases where it is known will improve diagnostics, but not affect the behavior of the returned effect.

@example

// Title: Wrapping a Callback API
import { Effect } from "effect"
import * as NodeFS from "node:fs"
const readFile = (filename: string) =>
Effect.async<Buffer, Error>((resume) => {
NodeFS.readFile(filename, (error, data) => {
if (error) {
// Resume with a failed Effect if an error occurs
resume(Effect.fail(error))
} else {
// Resume with a succeeded Effect if successful
resume(Effect.succeed(data))
}
})
})
// ┌─── Effect<Buffer, Error, never>
// ▼
const program = readFile("example.txt")

@example

// Title: Handling Interruption with Cleanup import { Effect, Fiber } from "effect" import * as NodeFS from "node:fs"

// Simulates a long-running operation to write to a file const writeFileWithCleanup = (filename: string, data: string) => Effect.async<void, Error>((resume) => { const writeStream = NodeFS.createWriteStream(filename)

// Start writing data to the file
writeStream.write(data)
// When the stream is finished, resume with success
writeStream.on("finish", () => resume(Effect.void))
// In case of an error during writing, resume with failure
writeStream.on("error", (err) => resume(Effect.fail(err)))
// Handle interruption by returning a cleanup effect
return Effect.sync(() => {
console.log(`Cleaning up ${filename}`)
NodeFS.unlinkSync(filename)
})

})

const program = Effect.gen(function* () { const fiber = yield* Effect.fork( writeFileWithCleanup("example.txt", "Some long data...") ) // Simulate interrupting the fiber after 1 second yield* Effect.sleep("1 second") yield* Fiber.interrupt(fiber) // This will trigger the cleanup })

// Run the program Effect.runPromise(program) // Output: // Cleaning up example.txt

@example

// Title: Handling Interruption with AbortSignal import { Effect, Fiber } from "effect"

// A task that supports interruption using AbortSignal const interruptibleTask = Effect.async<void, Error>((resume, signal) => { // Handle interruption signal.addEventListener("abort", () => { console.log("Abort signal received") clearTimeout(timeoutId) })

// Simulate a long-running task const timeoutId = setTimeout(() => { console.log("Operation completed") resume(Effect.void) }, 2000) })

const program = Effect.gen(function* () { const fiber = yield* Effect.fork(interruptibleTask) // Simulate interrupting the fiber after 1 second yield* Effect.sleep("1 second") yield* Fiber.interrupt(fiber) })

// Run the program Effect.runPromise(program) // Output: // Abort signal received

@since2.0.0

async
<void,
interface Error
Error
>((
resume: (_: Effect.Effect<void, Error, never>) => void
resume
,
signal: AbortSignal
signal
) => {
// Handle interruption
signal: AbortSignal
signal
.
function addEventListener(type: string, listener: EventListener | EventListenerObject, options?: AddEventListenerOptions | boolean): void

Adds a new handler for the type event. Any given listener is added only once per type and per capture option value.

If the once option is true, the listener is removed after the next time a type event is dispatched.

The capture option is not used by Node.js in any functional way other than tracking registered event listeners per the EventTarget specification. Specifically, the capture option is used as part of the key when registering a listener. Any individual listener may be added once with capture = false, and once with capture = true.

addEventListener
("abort", () => {
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
("Abort signal received")
function clearTimeout(timeoutId: NodeJS.Timeout | string | number | undefined): void

Cancels a Timeout object created by setTimeout().

@sincev0.0.1

@paramtimeout A Timeout object as returned by setTimeout or the primitive of the Timeout object as a string or a number.

clearTimeout
(
const timeoutId: NodeJS.Timeout
timeoutId
)
})
// Simulate a long-running task
const
const timeoutId: NodeJS.Timeout
timeoutId
=
function setTimeout<[]>(callback: () => void, ms?: number): NodeJS.Timeout (+1 overload)

Schedules execution of a one-time callback after delay milliseconds.

The callback will likely not be invoked in precisely delay milliseconds. Node.js makes no guarantees about the exact timing of when callbacks will fire, nor of their ordering. The callback will be called as close as possible to the time specified.

When delay is larger than 2147483647 or less than 1, the delay will be set to 1. Non-integer delays are truncated to an integer.

If callback is not a function, a TypeError will be thrown.

This method has a custom variant for promises that is available using timersPromises.setTimeout().

@sincev0.0.1

@paramcallback The function to call when the timer elapses.

@paramdelay The number of milliseconds to wait before calling the callback.

@paramargs Optional arguments to pass when the callback is called.

setTimeout
(() => {
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
("Operation completed")
resume: (_: Effect.Effect<void, Error, never>) => void
resume
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const void: Effect.Effect<void, never, never>
export void

@since2.0.0

void
)
}, 2000)
})
const
const program: Effect.Effect<void, never, never>
program
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, void, never>) => Effect.Effect<...> (+1 overload)

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to Use

gen allows you to write code that looks and behaves like synchronous code, but it can handle asynchronous tasks, errors, and complex control flow (like loops and conditions). It helps make asynchronous code more readable and easier to manage.

The generator functions work similarly to async/await but with more explicit control over the execution of effects. You can yield* values from effects and return the final result at the end.

@example

import { Effect } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function* () {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})

@since2.0.0

gen
(function* () {
const
const fiber: Fiber.RuntimeFiber<void, Error>
fiber
= yield*
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const fork: <void, Error, never>(self: Effect.Effect<void, Error, never>) => Effect.Effect<Fiber.RuntimeFiber<void, Error>, never, never>

Returns an effect that forks this effect into its own separate fiber, returning the fiber immediately, without waiting for it to begin executing the effect.

You can use the fork method whenever you want to execute an effect in a new fiber, concurrently and without "blocking" the fiber executing other effects. Using fibers can be tricky, so instead of using this method directly, consider other higher-level methods, such as raceWith, zipPar, and so forth.

The fiber returned by this method has methods to interrupt the fiber and to wait for it to finish executing the effect. See Fiber for more information.

Whenever you use this method to launch a new fiber, the new fiber is attached to the parent fiber's scope. This means when the parent fiber terminates, the child fiber will be terminated as well, ensuring that no fibers leak. This behavior is called "auto supervision", and if this behavior is not desired, you may use the forkDaemon or forkIn methods.

@since2.0.0

fork
(
const interruptibleTask: Effect.Effect<void, Error, never>
interruptibleTask
)
// Simulate interrupting the fiber after 1 second
yield*
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const sleep: (duration: DurationInput) => Effect.Effect<void>

Returns an effect that suspends for the specified duration. This method is asynchronous, and does not actually block the fiber executing the effect.

@since2.0.0

sleep
("1 second")
yield*
import Fiber
Fiber
.
const interrupt: <void, Error>(self: Fiber.Fiber<void, Error>) => Effect.Effect<Exit<void, Error>, never, never>

Interrupts the fiber from whichever fiber is calling this method. If the fiber has already exited, the returned effect will resume immediately. Otherwise, the effect will resume when the fiber exits.

@since2.0.0

interrupt
(
const fiber: Fiber.RuntimeFiber<void, Error>
fiber
)
})
// Run the program
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const runPromise: <void, never>(effect: Effect.Effect<void, never, never>, options?: {
readonly signal?: AbortSignal;
} | undefined) => Promise<void>

Executes an effect and returns the result as a Promise.

When to Use

Use runPromise when you need to execute an effect and work with the result using Promise syntax, typically for compatibility with other promise-based code.

If the effect succeeds, the promise will resolve with the result. If the effect fails, the promise will reject with an error.

@seerunPromiseExit for a version that returns an Exit type instead of rejecting.

@example

// Title: Running a Successful Effect as a Promise
import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

@example

//Example: Handling a Failing Effect as a Rejected Promise import { Effect } from "effect"

Effect.runPromise(Effect.fail("my error")).catch(console.error) // Output: // (FiberFailure) Error: my error

@since2.0.0

runPromise
(
const program: Effect.Effect<void, never, never>
program
)
/*
Output:
Abort signal received
*/

Effect.suspend is used to delay the creation of an effect. It allows you to defer the evaluation of an effect until it is actually needed. The Effect.suspend function takes a thunk that represents the effect, and it wraps it in a suspended effect.

Syntax

const suspendedEffect = Effect.suspend(() => effect)

Let’s explore some common scenarios where Effect.suspend proves useful.

When you want to defer the evaluation of an effect until it is required. This can be useful for optimizing the execution of effects, especially when they are not always needed or when their computation is expensive.

Also, when effects with side effects or scoped captures are created, use Effect.suspend to re-execute on each invocation.

Example (Lazy Evaluation with Side Effects)

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
} from "effect"
let
let i: number
i
= 0
const
const bad: Effect.Effect<number, never, never>
bad
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const succeed: <number>(value: number) => Effect.Effect<number, never, never>

Creates an Effect that always succeeds with a given value.

When to Use

Use this function when you need an effect that completes successfully with a specific value without any errors or external dependencies.

@seefail to create an effect that represents a failure.

@example

// Title: Creating a Successful Effect
import { Effect } from "effect"
// Creating an effect that represents a successful scenario
//
// ┌─── Effect<number, never, never>
// ▼
const success = Effect.succeed(42)

@since2.0.0

succeed
(
let i: number
i
++)
const
const good: Effect.Effect<number, never, never>
good
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const suspend: <number, never, never>(effect: LazyArg<Effect.Effect<number, never, never>>) => Effect.Effect<number, never, never>

Delays the creation of an Effect until it is actually needed.

When to Use

Use suspend when you need to defer the evaluation of an effect until it is required. This is particularly useful for optimizing expensive computations, managing circular dependencies, or resolving type inference issues.

Details

suspend takes a thunk that represents the effect and wraps it in a suspended effect. This means the effect will not be created until it is explicitly needed, which is helpful in various scenarios:

  • Lazy Evaluation: Helps optimize performance by deferring computations, especially when the effect might not be needed, or when its computation is expensive. This also ensures that any side effects or scoped captures are re-executed on each invocation.
  • Handling Circular Dependencies: Useful in managing circular dependencies, such as recursive functions that need to avoid eager evaluation to prevent stack overflow.
  • Unifying Return Types: Can help TypeScript unify return types in situations where multiple branches of logic return different effects, simplifying type inference.

@example

// Title: Lazy Evaluation with Side Effects
import { Effect } from "effect"
let i = 0
const bad = Effect.succeed(i++)
const good = Effect.suspend(() => Effect.succeed(i++))
console.log(Effect.runSync(bad)) // Output: 0
console.log(Effect.runSync(bad)) // Output: 0
console.log(Effect.runSync(good)) // Output: 1
console.log(Effect.runSync(good)) // Output: 2

@example

// Title: Recursive Fibonacci import { Effect } from "effect"

const blowsUp = (n: number): Effect.Effect => n < 2 ? Effect.succeed(1) : Effect.zipWith(blowsUp(n - 1), blowsUp(n - 2), (a, b) => a + b)

// console.log(Effect.runSync(blowsUp(32))) // crash: JavaScript heap out of memory

const allGood = (n: number): Effect.Effect => n < 2 ? Effect.succeed(1) : Effect.zipWith( Effect.suspend(() => allGood(n - 1)), Effect.suspend(() => allGood(n - 2)), (a, b) => a + b )

console.log(Effect.runSync(allGood(32))) // Output: 3524578

@example

// Title: Using Effect.suspend to Help TypeScript Infer Types import { Effect } from "effect"

// Without suspend, TypeScript may struggle with type inference. // Inferred type: // (a: number, b: number) => // Effect<never, Error, never> | Effect<number, never, never> const withoutSuspend = (a: number, b: number) => b === 0 ? Effect.fail(new Error("Cannot divide by zero")) : Effect.succeed(a / b)

// Using suspend to unify return types. // Inferred type: // (a: number, b: number) => Effect<number, Error, never> const withSuspend = (a: number, b: number) => Effect.suspend(() => b === 0 ? Effect.fail(new Error("Cannot divide by zero")) : Effect.succeed(a / b) )

@since2.0.0

suspend
(() =>
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const succeed: <number>(value: number) => Effect.Effect<number, never, never>

Creates an Effect that always succeeds with a given value.

When to Use

Use this function when you need an effect that completes successfully with a specific value without any errors or external dependencies.

@seefail to create an effect that represents a failure.

@example

// Title: Creating a Successful Effect
import { Effect } from "effect"
// Creating an effect that represents a successful scenario
//
// ┌─── Effect<number, never, never>
// ▼
const success = Effect.succeed(42)

@since2.0.0

succeed
(
let i: number
i
++))
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const runSync: <number, never>(effect: Effect.Effect<number, never, never>) => number

Executes an effect synchronously, running it immediately and returning the result.

When to Use

Use runSync to run an effect that does not fail and does not include any asynchronous operations.

If the effect fails or involves asynchronous work, it will throw an error, and execution will stop where the failure or async operation occurs.

@seerunSyncExit for a version that returns an Exit type instead of throwing an error.

@example

// Title: Synchronous Logging
import { Effect } from "effect"
const program = Effect.sync(() => {
console.log("Hello, World!")
return 1
})
const result = Effect.runSync(program)
// Output: Hello, World!
console.log(result)
// Output: 1

@example

// Title: Incorrect Usage with Failing or Async Effects import { Effect } from "effect"

try { // Attempt to run an effect that fails Effect.runSync(Effect.fail("my error")) } catch (e) { console.error(e) } // Output: // (FiberFailure) Error: my error

try { // Attempt to run an effect that involves async work Effect.runSync(Effect.promise(() => Promise.resolve(1))) } catch (e) { console.error(e) } // Output: // (FiberFailure) AsyncFiberException: Fiber #0 cannot be resolved synchronously. This is caused by using runSync on an effect that performs async work

@since2.0.0

runSync
(
const bad: Effect.Effect<number, never, never>
bad
)) // Output: 0
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const runSync: <number, never>(effect: Effect.Effect<number, never, never>) => number

Executes an effect synchronously, running it immediately and returning the result.

When to Use

Use runSync to run an effect that does not fail and does not include any asynchronous operations.

If the effect fails or involves asynchronous work, it will throw an error, and execution will stop where the failure or async operation occurs.

@seerunSyncExit for a version that returns an Exit type instead of throwing an error.

@example

// Title: Synchronous Logging
import { Effect } from "effect"
const program = Effect.sync(() => {
console.log("Hello, World!")
return 1
})
const result = Effect.runSync(program)
// Output: Hello, World!
console.log(result)
// Output: 1

@example

// Title: Incorrect Usage with Failing or Async Effects import { Effect } from "effect"

try { // Attempt to run an effect that fails Effect.runSync(Effect.fail("my error")) } catch (e) { console.error(e) } // Output: // (FiberFailure) Error: my error

try { // Attempt to run an effect that involves async work Effect.runSync(Effect.promise(() => Promise.resolve(1))) } catch (e) { console.error(e) } // Output: // (FiberFailure) AsyncFiberException: Fiber #0 cannot be resolved synchronously. This is caused by using runSync on an effect that performs async work

@since2.0.0

runSync
(
const bad: Effect.Effect<number, never, never>
bad
)) // Output: 0
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const runSync: <number, never>(effect: Effect.Effect<number, never, never>) => number

Executes an effect synchronously, running it immediately and returning the result.

When to Use

Use runSync to run an effect that does not fail and does not include any asynchronous operations.

If the effect fails or involves asynchronous work, it will throw an error, and execution will stop where the failure or async operation occurs.

@seerunSyncExit for a version that returns an Exit type instead of throwing an error.

@example

// Title: Synchronous Logging
import { Effect } from "effect"
const program = Effect.sync(() => {
console.log("Hello, World!")
return 1
})
const result = Effect.runSync(program)
// Output: Hello, World!
console.log(result)
// Output: 1

@example

// Title: Incorrect Usage with Failing or Async Effects import { Effect } from "effect"

try { // Attempt to run an effect that fails Effect.runSync(Effect.fail("my error")) } catch (e) { console.error(e) } // Output: // (FiberFailure) Error: my error

try { // Attempt to run an effect that involves async work Effect.runSync(Effect.promise(() => Promise.resolve(1))) } catch (e) { console.error(e) } // Output: // (FiberFailure) AsyncFiberException: Fiber #0 cannot be resolved synchronously. This is caused by using runSync on an effect that performs async work

@since2.0.0

runSync
(
const good: Effect.Effect<number, never, never>
good
)) // Output: 1
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const runSync: <number, never>(effect: Effect.Effect<number, never, never>) => number

Executes an effect synchronously, running it immediately and returning the result.

When to Use

Use runSync to run an effect that does not fail and does not include any asynchronous operations.

If the effect fails or involves asynchronous work, it will throw an error, and execution will stop where the failure or async operation occurs.

@seerunSyncExit for a version that returns an Exit type instead of throwing an error.

@example

// Title: Synchronous Logging
import { Effect } from "effect"
const program = Effect.sync(() => {
console.log("Hello, World!")
return 1
})
const result = Effect.runSync(program)
// Output: Hello, World!
console.log(result)
// Output: 1

@example

// Title: Incorrect Usage with Failing or Async Effects import { Effect } from "effect"

try { // Attempt to run an effect that fails Effect.runSync(Effect.fail("my error")) } catch (e) { console.error(e) } // Output: // (FiberFailure) Error: my error

try { // Attempt to run an effect that involves async work Effect.runSync(Effect.promise(() => Promise.resolve(1))) } catch (e) { console.error(e) } // Output: // (FiberFailure) AsyncFiberException: Fiber #0 cannot be resolved synchronously. This is caused by using runSync on an effect that performs async work

@since2.0.0

runSync
(
const good: Effect.Effect<number, never, never>
good
)) // Output: 2

In this example, bad is the result of calling Effect.succeed(i++) a single time, which increments the scoped variable but returns its original value. Effect.runSync(bad) does not result in any new computation, because Effect.succeed(i++) has already been called. On the other hand, each time Effect.runSync(good) is called, the thunk passed to Effect.suspend() will be executed, outputting the scoped variable’s most recent value.

Effect.suspend is helpful in managing circular dependencies between effects, where one effect depends on another, and vice versa. For example it’s fairly common for Effect.suspend to be used in recursive functions to escape an eager call.

Example (Recursive Fibonacci)

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
} from "effect"
const
const blowsUp: (n: number) => Effect.Effect<number>
blowsUp
= (
n: number
n
: number):
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
interface Effect<out A, out E = never, out R = never>

The Effect interface defines a value that lazily describes a workflow or job. The workflow requires some context R, and may fail with an error of type E, or succeed with a value of type A.

Effect values model resourceful interaction with the outside world, including synchronous, asynchronous, concurrent, and parallel interaction. They use a fiber-based concurrency model, with built-in support for scheduling, fine-grained interruption, structured concurrency, and high scalability.

To run an Effect value, you need a Runtime, which is a type that is capable of executing Effect values.

@since2.0.0

@since2.0.0

Effect
<number> =>
n: number
n
< 2
?
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const succeed: <number>(value: number) => Effect.Effect<number, never, never>

Creates an Effect that always succeeds with a given value.

When to Use

Use this function when you need an effect that completes successfully with a specific value without any errors or external dependencies.

@seefail to create an effect that represents a failure.

@example

// Title: Creating a Successful Effect
import { Effect } from "effect"
// Creating an effect that represents a successful scenario
//
// ┌─── Effect<number, never, never>
// ▼
const success = Effect.succeed(42)

@since2.0.0

succeed
(1)
:
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const zipWith: <number, never, never, number, never, never, number>(self: Effect.Effect<number, never, never>, that: Effect.Effect<number, never, never>, f: (a: number, b: number) => number, options?: {
readonly concurrent?: boolean | undefined;
readonly batching?: boolean | "inherit" | undefined;
readonly concurrentFinalizers?: boolean | undefined;
}) => Effect.Effect<...> (+1 overload)

Combines two effects sequentially and applies a function to their results to produce a single value.

When to Use

The zipWith function is similar to

zip

, but instead of returning a tuple of results, it applies a provided function to the results of the two effects, combining them into a single value.

Concurrency

By default, the effects are run sequentially. To execute them concurrently, use the { concurrent: true } option.

@example

// Title: Combining Effects with a Custom Function
import { Effect } from "effect"
const task1 = Effect.succeed(1).pipe(
Effect.delay("200 millis"),
Effect.tap(Effect.log("task1 done"))
)
const task2 = Effect.succeed("hello").pipe(
Effect.delay("100 millis"),
Effect.tap(Effect.log("task2 done"))
)
const task3 = Effect.zipWith(
task1,
task2,
// Combines results into a single value
(number, string) => number + string.length
)
Effect.runPromise(task3).then(console.log)
// Output:
// timestamp=... level=INFO fiber=#3 message="task1 done"
// timestamp=... level=INFO fiber=#2 message="task2 done"
// 6

@since2.0.0

zipWith
(
const blowsUp: (n: number) => Effect.Effect<number>
blowsUp
(
n: number
n
- 1),
const blowsUp: (n: number) => Effect.Effect<number>
blowsUp
(
n: number
n
- 2), (
a: number
a
,
b: number
b
) =>
a: number
a
+
b: number
b
)
// console.log(Effect.runSync(blowsUp(32)))
// crash: JavaScript heap out of memory
const
const allGood: (n: number) => Effect.Effect<number>
allGood
= (
n: number
n
: number):
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
interface Effect<out A, out E = never, out R = never>

The Effect interface defines a value that lazily describes a workflow or job. The workflow requires some context R, and may fail with an error of type E, or succeed with a value of type A.

Effect values model resourceful interaction with the outside world, including synchronous, asynchronous, concurrent, and parallel interaction. They use a fiber-based concurrency model, with built-in support for scheduling, fine-grained interruption, structured concurrency, and high scalability.

To run an Effect value, you need a Runtime, which is a type that is capable of executing Effect values.

@since2.0.0

@since2.0.0

Effect
<number> =>
n: number
n
< 2
?
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const succeed: <number>(value: number) => Effect.Effect<number, never, never>

Creates an Effect that always succeeds with a given value.

When to Use

Use this function when you need an effect that completes successfully with a specific value without any errors or external dependencies.

@seefail to create an effect that represents a failure.

@example

// Title: Creating a Successful Effect
import { Effect } from "effect"
// Creating an effect that represents a successful scenario
//
// ┌─── Effect<number, never, never>
// ▼
const success = Effect.succeed(42)

@since2.0.0

succeed
(1)
:
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const zipWith: <number, never, never, number, never, never, number>(self: Effect.Effect<number, never, never>, that: Effect.Effect<number, never, never>, f: (a: number, b: number) => number, options?: {
readonly concurrent?: boolean | undefined;
readonly batching?: boolean | "inherit" | undefined;
readonly concurrentFinalizers?: boolean | undefined;
}) => Effect.Effect<...> (+1 overload)

Combines two effects sequentially and applies a function to their results to produce a single value.

When to Use

The zipWith function is similar to

zip

, but instead of returning a tuple of results, it applies a provided function to the results of the two effects, combining them into a single value.

Concurrency

By default, the effects are run sequentially. To execute them concurrently, use the { concurrent: true } option.

@example

// Title: Combining Effects with a Custom Function
import { Effect } from "effect"
const task1 = Effect.succeed(1).pipe(
Effect.delay("200 millis"),
Effect.tap(Effect.log("task1 done"))
)
const task2 = Effect.succeed("hello").pipe(
Effect.delay("100 millis"),
Effect.tap(Effect.log("task2 done"))
)
const task3 = Effect.zipWith(
task1,
task2,
// Combines results into a single value
(number, string) => number + string.length
)
Effect.runPromise(task3).then(console.log)
// Output:
// timestamp=... level=INFO fiber=#3 message="task1 done"
// timestamp=... level=INFO fiber=#2 message="task2 done"
// 6

@since2.0.0

zipWith
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const suspend: <number, never, never>(effect: LazyArg<Effect.Effect<number, never, never>>) => Effect.Effect<number, never, never>

Delays the creation of an Effect until it is actually needed.

When to Use

Use suspend when you need to defer the evaluation of an effect until it is required. This is particularly useful for optimizing expensive computations, managing circular dependencies, or resolving type inference issues.

Details

suspend takes a thunk that represents the effect and wraps it in a suspended effect. This means the effect will not be created until it is explicitly needed, which is helpful in various scenarios:

  • Lazy Evaluation: Helps optimize performance by deferring computations, especially when the effect might not be needed, or when its computation is expensive. This also ensures that any side effects or scoped captures are re-executed on each invocation.
  • Handling Circular Dependencies: Useful in managing circular dependencies, such as recursive functions that need to avoid eager evaluation to prevent stack overflow.
  • Unifying Return Types: Can help TypeScript unify return types in situations where multiple branches of logic return different effects, simplifying type inference.

@example

// Title: Lazy Evaluation with Side Effects
import { Effect } from "effect"
let i = 0
const bad = Effect.succeed(i++)
const good = Effect.suspend(() => Effect.succeed(i++))
console.log(Effect.runSync(bad)) // Output: 0
console.log(Effect.runSync(bad)) // Output: 0
console.log(Effect.runSync(good)) // Output: 1
console.log(Effect.runSync(good)) // Output: 2

@example

// Title: Recursive Fibonacci import { Effect } from "effect"

const blowsUp = (n: number): Effect.Effect => n < 2 ? Effect.succeed(1) : Effect.zipWith(blowsUp(n - 1), blowsUp(n - 2), (a, b) => a + b)

// console.log(Effect.runSync(blowsUp(32))) // crash: JavaScript heap out of memory

const allGood = (n: number): Effect.Effect => n < 2 ? Effect.succeed(1) : Effect.zipWith( Effect.suspend(() => allGood(n - 1)), Effect.suspend(() => allGood(n - 2)), (a, b) => a + b )

console.log(Effect.runSync(allGood(32))) // Output: 3524578

@example

// Title: Using Effect.suspend to Help TypeScript Infer Types import { Effect } from "effect"

// Without suspend, TypeScript may struggle with type inference. // Inferred type: // (a: number, b: number) => // Effect<never, Error, never> | Effect<number, never, never> const withoutSuspend = (a: number, b: number) => b === 0 ? Effect.fail(new Error("Cannot divide by zero")) : Effect.succeed(a / b)

// Using suspend to unify return types. // Inferred type: // (a: number, b: number) => Effect<number, Error, never> const withSuspend = (a: number, b: number) => Effect.suspend(() => b === 0 ? Effect.fail(new Error("Cannot divide by zero")) : Effect.succeed(a / b) )

@since2.0.0

suspend
(() =>
const allGood: (n: number) => Effect.Effect<number>
allGood
(
n: number
n
- 1)),
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const suspend: <number, never, never>(effect: LazyArg<Effect.Effect<number, never, never>>) => Effect.Effect<number, never, never>

Delays the creation of an Effect until it is actually needed.

When to Use

Use suspend when you need to defer the evaluation of an effect until it is required. This is particularly useful for optimizing expensive computations, managing circular dependencies, or resolving type inference issues.

Details

suspend takes a thunk that represents the effect and wraps it in a suspended effect. This means the effect will not be created until it is explicitly needed, which is helpful in various scenarios:

  • Lazy Evaluation: Helps optimize performance by deferring computations, especially when the effect might not be needed, or when its computation is expensive. This also ensures that any side effects or scoped captures are re-executed on each invocation.
  • Handling Circular Dependencies: Useful in managing circular dependencies, such as recursive functions that need to avoid eager evaluation to prevent stack overflow.
  • Unifying Return Types: Can help TypeScript unify return types in situations where multiple branches of logic return different effects, simplifying type inference.

@example

// Title: Lazy Evaluation with Side Effects
import { Effect } from "effect"
let i = 0
const bad = Effect.succeed(i++)
const good = Effect.suspend(() => Effect.succeed(i++))
console.log(Effect.runSync(bad)) // Output: 0
console.log(Effect.runSync(bad)) // Output: 0
console.log(Effect.runSync(good)) // Output: 1
console.log(Effect.runSync(good)) // Output: 2

@example

// Title: Recursive Fibonacci import { Effect } from "effect"

const blowsUp = (n: number): Effect.Effect => n < 2 ? Effect.succeed(1) : Effect.zipWith(blowsUp(n - 1), blowsUp(n - 2), (a, b) => a + b)

// console.log(Effect.runSync(blowsUp(32))) // crash: JavaScript heap out of memory

const allGood = (n: number): Effect.Effect => n < 2 ? Effect.succeed(1) : Effect.zipWith( Effect.suspend(() => allGood(n - 1)), Effect.suspend(() => allGood(n - 2)), (a, b) => a + b )

console.log(Effect.runSync(allGood(32))) // Output: 3524578

@example

// Title: Using Effect.suspend to Help TypeScript Infer Types import { Effect } from "effect"

// Without suspend, TypeScript may struggle with type inference. // Inferred type: // (a: number, b: number) => // Effect<never, Error, never> | Effect<number, never, never> const withoutSuspend = (a: number, b: number) => b === 0 ? Effect.fail(new Error("Cannot divide by zero")) : Effect.succeed(a / b)

// Using suspend to unify return types. // Inferred type: // (a: number, b: number) => Effect<number, Error, never> const withSuspend = (a: number, b: number) => Effect.suspend(() => b === 0 ? Effect.fail(new Error("Cannot divide by zero")) : Effect.succeed(a / b) )

@since2.0.0

suspend
(() =>
const allGood: (n: number) => Effect.Effect<number>
allGood
(
n: number
n
- 2)),
(
a: number
a
,
b: number
b
) =>
a: number
a
+
b: number
b
)
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const runSync: <number, never>(effect: Effect.Effect<number, never, never>) => number

Executes an effect synchronously, running it immediately and returning the result.

When to Use

Use runSync to run an effect that does not fail and does not include any asynchronous operations.

If the effect fails or involves asynchronous work, it will throw an error, and execution will stop where the failure or async operation occurs.

@seerunSyncExit for a version that returns an Exit type instead of throwing an error.

@example

// Title: Synchronous Logging
import { Effect } from "effect"
const program = Effect.sync(() => {
console.log("Hello, World!")
return 1
})
const result = Effect.runSync(program)
// Output: Hello, World!
console.log(result)
// Output: 1

@example

// Title: Incorrect Usage with Failing or Async Effects import { Effect } from "effect"

try { // Attempt to run an effect that fails Effect.runSync(Effect.fail("my error")) } catch (e) { console.error(e) } // Output: // (FiberFailure) Error: my error

try { // Attempt to run an effect that involves async work Effect.runSync(Effect.promise(() => Promise.resolve(1))) } catch (e) { console.error(e) } // Output: // (FiberFailure) AsyncFiberException: Fiber #0 cannot be resolved synchronously. This is caused by using runSync on an effect that performs async work

@since2.0.0

runSync
(
const allGood: (n: number) => Effect.Effect<number>
allGood
(32))) // Output: 3524578

The blowsUp function creates a recursive Fibonacci sequence without deferring execution. Each call to blowsUp triggers further immediate recursive calls, rapidly increasing the JavaScript call stack size.

Conversely, allGood avoids stack overflow by using Effect.suspend to defer the recursive calls. This mechanism doesn’t immediately execute the recursive effects but schedules them to be run later, thus keeping the call stack shallow and preventing a crash.

In situations where TypeScript struggles to unify the returned effect type, Effect.suspend can be employed to resolve this issue.

Example (Using Effect.suspend to Help TypeScript Infer Types)

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
} from "effect"
/*
Without suspend, TypeScript may struggle with type inference.
Inferred type:
(a: number, b: number) =>
Effect<never, Error, never> | Effect<number, never, never>
*/
const
const withoutSuspend: (a: number, b: number) => Effect.Effect<never, Error, never> | Effect.Effect<number, never, never>
withoutSuspend
= (
a: number
a
: number,
b: number
b
: number) =>
b: number
b
=== 0
?
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const fail: <Error>(error: Error) => Effect.Effect<never, Error, never>

Creates an Effect that represents a recoverable error.

When to Use

Use this function to explicitly signal an error in an Effect. The error will keep propagating unless it is handled. You can handle the error with functions like

catchAll

or

catchTag

.

@seesucceed to create an effect that represents a successful value.

@example

// Title: Creating a Failed Effect
import { Effect } from "effect"
// ┌─── Effect<never, Error, never>
// ▼
const failure = Effect.fail(
new Error("Operation failed due to network error")
)

@since2.0.0

fail
(new
var Error: ErrorConstructor
new (message?: string) => Error
Error
("Cannot divide by zero"))
:
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const succeed: <number>(value: number) => Effect.Effect<number, never, never>

Creates an Effect that always succeeds with a given value.

When to Use

Use this function when you need an effect that completes successfully with a specific value without any errors or external dependencies.

@seefail to create an effect that represents a failure.

@example

// Title: Creating a Successful Effect
import { Effect } from "effect"
// Creating an effect that represents a successful scenario
//
// ┌─── Effect<number, never, never>
// ▼
const success = Effect.succeed(42)

@since2.0.0

succeed
(
a: number
a
/
b: number
b
)
/*
Using suspend to unify return types.
Inferred type:
(a: number, b: number) => Effect<number, Error, never>
*/
const
const withSuspend: (a: number, b: number) => Effect.Effect<number, Error, never>
withSuspend
= (
a: number
a
: number,
b: number
b
: number) =>
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const suspend: <number, Error, never>(effect: LazyArg<Effect.Effect<number, Error, never>>) => Effect.Effect<number, Error, never>

Delays the creation of an Effect until it is actually needed.

When to Use

Use suspend when you need to defer the evaluation of an effect until it is required. This is particularly useful for optimizing expensive computations, managing circular dependencies, or resolving type inference issues.

Details

suspend takes a thunk that represents the effect and wraps it in a suspended effect. This means the effect will not be created until it is explicitly needed, which is helpful in various scenarios:

  • Lazy Evaluation: Helps optimize performance by deferring computations, especially when the effect might not be needed, or when its computation is expensive. This also ensures that any side effects or scoped captures are re-executed on each invocation.
  • Handling Circular Dependencies: Useful in managing circular dependencies, such as recursive functions that need to avoid eager evaluation to prevent stack overflow.
  • Unifying Return Types: Can help TypeScript unify return types in situations where multiple branches of logic return different effects, simplifying type inference.

@example

// Title: Lazy Evaluation with Side Effects
import { Effect } from "effect"
let i = 0
const bad = Effect.succeed(i++)
const good = Effect.suspend(() => Effect.succeed(i++))
console.log(Effect.runSync(bad)) // Output: 0
console.log(Effect.runSync(bad)) // Output: 0
console.log(Effect.runSync(good)) // Output: 1
console.log(Effect.runSync(good)) // Output: 2

@example

// Title: Recursive Fibonacci import { Effect } from "effect"

const blowsUp = (n: number): Effect.Effect => n < 2 ? Effect.succeed(1) : Effect.zipWith(blowsUp(n - 1), blowsUp(n - 2), (a, b) => a + b)

// console.log(Effect.runSync(blowsUp(32))) // crash: JavaScript heap out of memory

const allGood = (n: number): Effect.Effect => n < 2 ? Effect.succeed(1) : Effect.zipWith( Effect.suspend(() => allGood(n - 1)), Effect.suspend(() => allGood(n - 2)), (a, b) => a + b )

console.log(Effect.runSync(allGood(32))) // Output: 3524578

@example

// Title: Using Effect.suspend to Help TypeScript Infer Types import { Effect } from "effect"

// Without suspend, TypeScript may struggle with type inference. // Inferred type: // (a: number, b: number) => // Effect<never, Error, never> | Effect<number, never, never> const withoutSuspend = (a: number, b: number) => b === 0 ? Effect.fail(new Error("Cannot divide by zero")) : Effect.succeed(a / b)

// Using suspend to unify return types. // Inferred type: // (a: number, b: number) => Effect<number, Error, never> const withSuspend = (a: number, b: number) => Effect.suspend(() => b === 0 ? Effect.fail(new Error("Cannot divide by zero")) : Effect.succeed(a / b) )

@since2.0.0

suspend
(() =>
b: number
b
=== 0
?
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const fail: <Error>(error: Error) => Effect.Effect<never, Error, never>

Creates an Effect that represents a recoverable error.

When to Use

Use this function to explicitly signal an error in an Effect. The error will keep propagating unless it is handled. You can handle the error with functions like

catchAll

or

catchTag

.

@seesucceed to create an effect that represents a successful value.

@example

// Title: Creating a Failed Effect
import { Effect } from "effect"
// ┌─── Effect<never, Error, never>
// ▼
const failure = Effect.fail(
new Error("Operation failed due to network error")
)

@since2.0.0

fail
(new
var Error: ErrorConstructor
new (message?: string) => Error
Error
("Cannot divide by zero"))
:
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const succeed: <number>(value: number) => Effect.Effect<number, never, never>

Creates an Effect that always succeeds with a given value.

When to Use

Use this function when you need an effect that completes successfully with a specific value without any errors or external dependencies.

@seefail to create an effect that represents a failure.

@example

// Title: Creating a Successful Effect
import { Effect } from "effect"
// Creating an effect that represents a successful scenario
//
// ┌─── Effect<number, never, never>
// ▼
const success = Effect.succeed(42)

@since2.0.0

succeed
(
a: number
a
/
b: number
b
)
)

The table provides a summary of the available constructors, along with their input and output types, allowing you to choose the appropriate function based on your needs.

APIGivenResult
succeedAEffect<A>
failEEffect<never, E>
sync() => AEffect<A>
try() => AEffect<A, UnknownException>
try (overload)() => A, unknown => EEffect<A, E>
promise() => Promise<A>Effect<A>
tryPromise() => Promise<A>Effect<A, UnknownException>
tryPromise (overload)() => Promise<A>, unknown => EEffect<A, E>
async(Effect<A, E> => void) => voidEffect<A, E>
suspend() => Effect<A, E, R>Effect<A, E, R>

For the complete list of constructors, visit the Effect Constructors Documentation.