In Effect you can perform various operations on the error channel of effects. These operations allow you to transform, inspect, and handle errors in different ways. Let’s explore some of these operations.
Map Operations
mapError
The Effect.mapError function is used when you need to transform or modify an error produced by an effect, without affecting the success value. This can be helpful when you want to add extra information to the error or change its type.
Example (Mapping an Error)
Here, the error type changes from string to Error.
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
.
@see ― succeed to create an effect that represents a successful value.
constas: <number>(value:number) => <A, E, R>(self:Effect.Effect<A, E, R>) =>Effect.Effect<number, E, R> (+1overload)
Replaces the value inside an effect with a constant value.
Details
This function allows you to ignore the original value inside an effect and
replace it with a constant value.
When to Use
It is useful when you no longer need the value produced by an effect but want
to ensure that the effect completes successfully with a specific constant
result instead. For instance, you can replace the value produced by a
computation with a predefined value, ignoring what was calculated before.
@example
// Title: Replacing a Value
import { pipe, Effect } from"effect"
// Replaces the value 5 with the constant "new value"
Transforms or modifies the error produced by an effect without affecting its
success value.
When to Use
This function is helpful when you want to enhance the error with additional
information, change the error type, or apply custom error handling while
keeping the original behavior of the effect's success values intact. It only
operates on the error channel and leaves the success channel unchanged.
@see ― map for a version that operates on the success channel.
@see ― mapBoth for a version that operates on both channels.
@see ― orElseFail if you want to replace the error with a new one.
The Effect.mapBoth function allows you to apply transformations to both channels: the error channel and the success channel of an effect. It takes two map functions as arguments: one for the error channel and the other for the success channel.
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
.
@see ― succeed to create an effect that represents a successful value.
constas: <number>(value:number) => <A, E, R>(self:Effect.Effect<A, E, R>) =>Effect.Effect<number, E, R> (+1overload)
Replaces the value inside an effect with a constant value.
Details
This function allows you to ignore the original value inside an effect and
replace it with a constant value.
When to Use
It is useful when you no longer need the value produced by an effect but want
to ensure that the effect completes successfully with a specific constant
result instead. For instance, you can replace the value produced by a
computation with a predefined value, ignoring what was calculated before.
@example
// Title: Replacing a Value
import { pipe, Effect } from"effect"
// Replaces the value 5 with the constant "new value"
Applies transformations to both the success and error channels of an effect.
Details
This function takes two map functions as arguments: one for the error channel
and one for the success channel. You can use it when you want to modify both
the error and the success values without altering the overall success or
failure status of the effect.
@see ― map for a version that operates on the success channel.
@see ― mapError for a version that operates on the error channel.
The Effect library provides several operators to filter values on the success channel based on a given predicate.
These operators offer different strategies for handling cases where the predicate fails:
API
Description
filterOrFail
This operator filters the values on the success channel based on a predicate. If the predicate fails for any value, the original effect fails with an error.
filterOrDie / filterOrDieMessage
These operators also filter the values on the success channel based on a predicate. If the predicate fails for any value, the original effect terminates abruptly. The filterOrDieMessage variant allows you to provide a custom error message.
filterOrElse
This operator filters the values on the success channel based on a predicate. If the predicate fails for any value, an alternative effect is executed instead.
Filters an effect, failing with a custom error if the predicate fails.
Details
This function applies a predicate to the result of an effect. If the
predicate evaluates to false, the effect fails with a custom error
generated by the orFailWith function.
When to Use
This is useful for enforcing constraints and treating violations as
recoverable errors.
Providing a Guard
In addition to the filtering capabilities discussed earlier, you have the
option to further refine and narrow down the type of the success channel by
providing a user-defined type
guard.
Let's explore this concept through an example:
@example
import { Effect, pipe } from"effect"
// Define a user interface
interfaceUser {
readonlyname:string
}
// Simulate an asynchronous authentication function
declareconstauth: () =>Promise<User|null>
constprogram=pipe(
Effect.promise(() =>auth()),
// Use filterOrFail with a custom type guard to ensure user is not null
Effect.filterOrFail(
(user):userisUser=> user !==null, // Type guard
() =>newError("Unauthorized")
),
// 'user' now has the type `User` (not `User | null`)
Filters an effect, dying with a custom defect if the predicate fails.
Details
This function applies a predicate to the result of an effect. If the
predicate evaluates to false, the effect dies with a custom defect
generated by the orDieWith function.
When to Use
This is useful for enforcing constraints on values and treating violations as
fatal program errors.
Creates an error indicating an invalid method argument.
Details
This function constructs an IllegalArgumentException. It is typically
thrown or returned when an operation receives improper inputs, such as
out-of-range values or invalid object states.
@since ― 2.0.0
IllegalArgumentException("random number is negative")
15
)
16
17
// Die with a custom error message if predicate is false
Filters an effect, dying with a custom message if the predicate fails.
Details
This function works like
filterOrDie
but allows you to specify a
custom error message to describe the reason for the failure. The message is
included in the defect when the predicate evaluates to false.
Filters an effect, providing an alternative effect if the predicate fails.
Details
This function applies a predicate to the result of an effect. If the
predicate evaluates to false, it executes the orElse effect instead. The
orElse effect can produce an alternative value or perform additional
computations.
Returns the next numeric value in the specified range from the
pseudo-random number generator.
@since ― 2.0.0
nextRange(-1, 1),
27
(
n: number
n) =>
n: number
n>=0,
28
() =>
consttask3:Effect.Effect<number, never, never>
task3
29
)
It’s important to note that depending on the specific filtering operator used, the effect can either fail, terminate abruptly, or execute an alternative effect when the predicate fails. Choose the appropriate operator based on your desired error handling strategy and program logic.
The filtering APIs can also be combined with user-defined type guards to improve type safety and code clarity. This ensures that only valid types pass through.
Example (Using a Type Guard)
1
import {
import Effect
@since ― 2.0.0
@since ― 2.0.0
@since ― 2.0.0
Effect,
functionpipe<A>(a:A):A (+19overloads)
Pipes the value of an expression into a pipeline of functions.
When to Use
This is useful in combination with data-last functions as a simulation of
methods:
as.map(f).filter(g)
becomes:
import { pipe, Array } from"effect"
pipe(as, Array.map(f), Array.filter(g))
Details
The pipe function is a utility that allows us to compose functions in a
readable and sequential manner. It takes the output of one function and
passes it as the input to the next function in the pipeline. This enables us
to build complex transformations by chaining multiple functions together.
import { pipe } from"effect"
constresult=pipe(input, func1, func2, ..., funcN)
In this syntax, input is the initial value, and func1, func2, ...,
funcN are the functions to be applied in sequence. The result of each
function becomes the input for the next function, and the final result is
returned.
Pipes the value of an expression into a pipeline of functions.
When to Use
This is useful in combination with data-last functions as a simulation of
methods:
as.map(f).filter(g)
becomes:
import { pipe, Array } from"effect"
pipe(as, Array.map(f), Array.filter(g))
Details
The pipe function is a utility that allows us to compose functions in a
readable and sequential manner. It takes the output of one function and
passes it as the input to the next function in the pipeline. This enables us
to build complex transformations by chaining multiple functions together.
import { pipe } from"effect"
constresult=pipe(input, func1, func2, ..., funcN)
In this syntax, input is the initial value, and func1, func2, ...,
funcN are the functions to be applied in sequence. The result of each
function becomes the input for the next function, and the final result is
returned.
Creates an Effect that represents an asynchronous computation guaranteed to
succeed.
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.
When to Use
Use this function when you are sure the operation will not reject.
@see ― tryPromise for a version that can handle failures.
Filters an effect, failing with a custom error if the predicate fails.
Details
This function applies a predicate to the result of an effect. If the
predicate evaluates to false, the effect fails with a custom error
generated by the orFailWith function.
When to Use
This is useful for enforcing constraints and treating violations as
recoverable errors.
Providing a Guard
In addition to the filtering capabilities discussed earlier, you have the
option to further refine and narrow down the type of the success channel by
providing a user-defined type
guard.
Let's explore this concept through an example:
@example
import { Effect, pipe } from"effect"
// Define a user interface
interfaceUser {
readonlyname:string
}
// Simulate an asynchronous authentication function
declareconstauth: () =>Promise<User|null>
constprogram=pipe(
Effect.promise(() =>auth()),
// Use filterOrFail with a custom type guard to ensure user is not null
Effect.filterOrFail(
(user):userisUser=> user !==null, // Type guard
() =>newError("Unauthorized")
),
// 'user' now has the type `User` (not `User | null`)
Effect.andThen((user) => user.name)
)
@since ― 2.0.0
filterOrFail(
15
(
user: User |null
user):
user: User |null
useris
interfaceUser
User=>
user: User |null
user!==null, // Type guard
16
() =>new
var Error:ErrorConstructor
new (message?:string) => Error
Error("Unauthorized")
17
),
18
// 'user' now has the type `User` (not `User | null`)
19
import Effect
@since ― 2.0.0
@since ― 2.0.0
@since ― 2.0.0
Effect.
constandThen: <User, string>(f: (a:User) =>string) => <E, R>(self:Effect.Effect<User, E, R>) =>Effect.Effect<string, E, R> (+3overloads)
Chains two actions, where the second action can depend on the result of the
first.
Use andThen when you need to run multiple actions in sequence, with the
second action depending on the result of the first. This is useful for
combining effects or handling computations that must happen in order.
Details
The second action can be:
A constant value (similar to
as
)
A function returning a value (similar to
map
)
A Promise
A function returning a Promise
An Effect
A function returning an Effect (similar to
flatMap
)
Note:andThen works well with both Option and Either types,
treating them as effects.
@example
// Title: Applying a Discount Based on Fetched Amount
import { pipe, Effect } from"effect"
// Function to apply a discount safely to a transaction amount
constapplyDiscount= (
total:number,
discountRate:number
):Effect.Effect<number, Error> =>
discountRate ===0
? Effect.fail(newError("Discount rate cannot be zero"))
In the example above, a guard is used within the filterOrFail API to ensure that the user is of type User rather than User | null.
If you prefer, you can utilize a pre-made guard like Predicate.isNotNull for simplicity and consistency.
Inspecting Errors
Similar to tapping for success values, Effect provides several operators for inspecting error values.
These operators allow developers to observe failures or underlying issues without modifying the outcome.
tapError
Executes an effectful operation to inspect the failure of an effect without altering it.
Example (Inspecting Errors)
1
import {
import Effect
@since ― 2.0.0
@since ― 2.0.0
@since ― 2.0.0
Effect,
import Console
Console } from"effect"
2
3
// Simulate a task that fails with an error
4
const
consttask:Effect.Effect<number, string, never>
task:
import Effect
@since ― 2.0.0
@since ― 2.0.0
@since ― 2.0.0
Effect.
interfaceEffect<outA, outE=never, outR=never>
The Effect interface defines a value that describes a workflow or job,
which can succeed or fail.
Details
The Effect interface represents a computation that can model a workflow
involving various types of operations, such as synchronous, asynchronous,
concurrent, and parallel interactions. It operates within a context of type
R, and the result can either be a success with a value of type A or a
failure with an error of type E. The Effect is designed to handle complex
interactions with external resources, offering advanced features such as
fiber-based concurrency, scheduling, interruption handling, and scalability.
This makes it suitable for tasks that require fine-grained control over
concurrency and error management.
To execute an Effect value, you need a Runtime, which provides the
environment necessary to run and manage the computation.
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
.
@see ― succeed to create an effect that represents a successful value.
@example
// Title: Creating a Failed Effect
import { Effect } from"effect"
// ┌─── Effect<never, Error, never>
// ▼
constfailure= Effect.fail(
newError("Operation failed due to network error")
)
@since ― 2.0.0
fail("NetworkError")
5
6
// Use tapError to log the error message when the task fails
Execute a side effect on failure without modifying the original effect.
Details
This function allows you to inspect and react to the failure of an effect by
executing an additional effect. The failure value is passed to the provided
function, enabling you to log it, track it, or perform any other operation.
Importantly, the original failure remains intact and is re-propagated, so the
effect's behavior is unchanged.
The side effect you provide is only executed when the effect fails. If the
effect succeeds, the function is ignored, and the success value is propagated
as usual.
Runs an effect in the background, returning a fiber that can be observed or
interrupted.
Unless you specifically need a Promise or synchronous operation, runFork
is a good default choice.
Details
This function is the foundational way to execute an effect in the background.
It creates a "fiber," a lightweight, cooperative thread of execution that can
be observed (to access its result), interrupted, or joined. Fibers are useful
for concurrent programming and allow effects to run independently of the main
program flow.
Once the effect is running in a fiber, you can monitor its progress, cancel
it if necessary, or retrieve its result when it completes. If the effect
fails, the fiber will propagate the failure, which you can observe and
handle.
When to Use
Use this function when you need to run an effect in the background,
especially if the effect is long-running or performs periodic tasks. It's
suitable for tasks that need to run independently but might still need
observation or management, like logging, monitoring, or scheduled tasks.
This function is ideal if you don't need the result immediately or if the
effect is part of a larger concurrent workflow.
The Effect interface defines a value that describes a workflow or job,
which can succeed or fail.
Details
The Effect interface represents a computation that can model a workflow
involving various types of operations, such as synchronous, asynchronous,
concurrent, and parallel interactions. It operates within a context of type
R, and the result can either be a success with a value of type A or a
failure with an error of type E. The Effect is designed to handle complex
interactions with external resources, offering advanced features such as
fiber-based concurrency, scheduling, interruption handling, and scalability.
This makes it suitable for tasks that require fine-grained control over
concurrency and error management.
To execute an Effect value, you need a Runtime, which provides the
environment necessary to run and manage the computation.
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
.
@see ― succeed to create an effect that represents a successful value.
Inspect errors matching a specific tag without altering the original effect.
Details
This function allows you to inspect and handle specific error types based on
their _tag property. It is particularly useful in applications where errors
are modeled with tagged types (e.g., union types with discriminating tags).
By targeting errors with a specific _tag, you can log or perform actions on
them while leaving the error channel and overall effect unchanged.
If the error doesn't match the specified tag, this function does nothing, and
the effect proceeds as usual.
Runs an effect in the background, returning a fiber that can be observed or
interrupted.
Unless you specifically need a Promise or synchronous operation, runFork
is a good default choice.
Details
This function is the foundational way to execute an effect in the background.
It creates a "fiber," a lightweight, cooperative thread of execution that can
be observed (to access its result), interrupted, or joined. Fibers are useful
for concurrent programming and allow effects to run independently of the main
program flow.
Once the effect is running in a fiber, you can monitor its progress, cancel
it if necessary, or retrieve its result when it completes. If the effect
fails, the fiber will propagate the failure, which you can observe and
handle.
When to Use
Use this function when you need to run an effect in the background,
especially if the effect is long-running or performs periodic tasks. It's
suitable for tasks that need to run independently but might still need
observation or management, like logging, monitoring, or scheduled tasks.
This function is ideal if you don't need the result immediately or if the
effect is part of a larger concurrent workflow.
This function inspects the complete cause of an error, including failures and defects.
Example (Inspecting Error Causes)
1
import {
import Effect
@since ― 2.0.0
@since ― 2.0.0
@since ― 2.0.0
Effect,
import Console
Console } from"effect"
2
3
// Create a task that fails with a NetworkError
4
const
consttask1:Effect.Effect<number, string, never>
task1:
import Effect
@since ― 2.0.0
@since ― 2.0.0
@since ― 2.0.0
Effect.
interfaceEffect<outA, outE=never, outR=never>
The Effect interface defines a value that describes a workflow or job,
which can succeed or fail.
Details
The Effect interface represents a computation that can model a workflow
involving various types of operations, such as synchronous, asynchronous,
concurrent, and parallel interactions. It operates within a context of type
R, and the result can either be a success with a value of type A or a
failure with an error of type E. The Effect is designed to handle complex
interactions with external resources, offering advanced features such as
fiber-based concurrency, scheduling, interruption handling, and scalability.
This makes it suitable for tasks that require fine-grained control over
concurrency and error management.
To execute an Effect value, you need a Runtime, which provides the
environment necessary to run and manage the computation.
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
.
@see ― succeed to create an effect that represents a successful value.
Inspect the complete cause of an error, including failures and defects.
Details
This function provides access to the full cause of an error, including both
recoverable failures and irrecoverable defects. It allows you to handle, log,
or monitor specific error causes without modifying the result of the effect.
The full Cause object encapsulates the error and its contextual
information, making it useful for debugging and understanding failure
scenarios in complex workflows.
The effect itself is not modified, and any errors or defects remain in the
error channel of the original effect.
Runs an effect in the background, returning a fiber that can be observed or
interrupted.
Unless you specifically need a Promise or synchronous operation, runFork
is a good default choice.
Details
This function is the foundational way to execute an effect in the background.
It creates a "fiber," a lightweight, cooperative thread of execution that can
be observed (to access its result), interrupted, or joined. Fibers are useful
for concurrent programming and allow effects to run independently of the main
program flow.
Once the effect is running in a fiber, you can monitor its progress, cancel
it if necessary, or retrieve its result when it completes. If the effect
fails, the fiber will propagate the failure, which you can observe and
handle.
When to Use
Use this function when you need to run an effect in the background,
especially if the effect is long-running or performs periodic tasks. It's
suitable for tasks that need to run independently but might still need
observation or management, like logging, monitoring, or scheduled tasks.
This function is ideal if you don't need the result immediately or if the
effect is part of a larger concurrent workflow.
The Effect interface defines a value that describes a workflow or job,
which can succeed or fail.
Details
The Effect interface represents a computation that can model a workflow
involving various types of operations, such as synchronous, asynchronous,
concurrent, and parallel interactions. It operates within a context of type
R, and the result can either be a success with a value of type A or a
failure with an error of type E. The Effect is designed to handle complex
interactions with external resources, offering advanced features such as
fiber-based concurrency, scheduling, interruption handling, and scalability.
This makes it suitable for tasks that require fine-grained control over
concurrency and error management.
To execute an Effect value, you need a Runtime, which provides the
environment necessary to run and manage the computation.
Creates an effect that terminates a fiber with a RuntimeException
containing the specified message.
Details
This function is used to signal a defect, representing a critical and
unexpected error in the code. When invoked, it produces an effect that
terminates the fiber with a RuntimeException carrying the given message.
The resulting effect has an error channel of type never, indicating it does
not handle or recover from the error.
When to Use
Use this function when you want to terminate a fiber due to an unrecoverable
defect and include a clear explanation in the message.
@see ― die for a variant that throws a specified error.
@see ― dieSync for a variant that throws a specified error, evaluated
lazily.
@example
// Title: Terminating on Division by Zero with a Specified Message
Inspect the complete cause of an error, including failures and defects.
Details
This function provides access to the full cause of an error, including both
recoverable failures and irrecoverable defects. It allows you to handle, log,
or monitor specific error causes without modifying the result of the effect.
The full Cause object encapsulates the error and its contextual
information, making it useful for debugging and understanding failure
scenarios in complex workflows.
The effect itself is not modified, and any errors or defects remain in the
error channel of the original effect.
Runs an effect in the background, returning a fiber that can be observed or
interrupted.
Unless you specifically need a Promise or synchronous operation, runFork
is a good default choice.
Details
This function is the foundational way to execute an effect in the background.
It creates a "fiber," a lightweight, cooperative thread of execution that can
be observed (to access its result), interrupted, or joined. Fibers are useful
for concurrent programming and allow effects to run independently of the main
program flow.
Once the effect is running in a fiber, you can monitor its progress, cancel
it if necessary, or retrieve its result when it completes. If the effect
fails, the fiber will propagate the failure, which you can observe and
handle.
When to Use
Use this function when you need to run an effect in the background,
especially if the effect is long-running or performs periodic tasks. It's
suitable for tasks that need to run independently but might still need
observation or management, like logging, monitoring, or scheduled tasks.
This function is ideal if you don't need the result immediately or if the
effect is part of a larger concurrent workflow.
error cause: RuntimeException: Something went wrong
29
... stack trace ...
30
*/
tapDefect
Specifically inspects non-recoverable failures or defects in an effect (i.e., one or more Die causes).
Example (Inspecting Defects)
1
import {
import Effect
@since ― 2.0.0
@since ― 2.0.0
@since ― 2.0.0
Effect,
import Console
Console } from"effect"
2
3
// Simulate a task that fails with a recoverable error
4
const
consttask1:Effect.Effect<number, string, never>
task1:
import Effect
@since ― 2.0.0
@since ― 2.0.0
@since ― 2.0.0
Effect.
interfaceEffect<outA, outE=never, outR=never>
The Effect interface defines a value that describes a workflow or job,
which can succeed or fail.
Details
The Effect interface represents a computation that can model a workflow
involving various types of operations, such as synchronous, asynchronous,
concurrent, and parallel interactions. It operates within a context of type
R, and the result can either be a success with a value of type A or a
failure with an error of type E. The Effect is designed to handle complex
interactions with external resources, offering advanced features such as
fiber-based concurrency, scheduling, interruption handling, and scalability.
This makes it suitable for tasks that require fine-grained control over
concurrency and error management.
To execute an Effect value, you need a Runtime, which provides the
environment necessary to run and manage the computation.
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
.
@see ― succeed to create an effect that represents a successful value.
@example
// Title: Creating a Failed Effect
import { Effect } from"effect"
// ┌─── Effect<never, Error, never>
// ▼
constfailure= Effect.fail(
newError("Operation failed due to network error")
)
@since ― 2.0.0
fail("NetworkError")
5
6
// tapDefect won't log anything because NetworkError is not a defect
Inspect severe errors or defects (non-recoverable failures) in an effect.
Details
This function is specifically designed to handle and inspect defects, which
are critical failures in your program, such as unexpected runtime exceptions
or system-level errors. Unlike normal recoverable errors, defects typically
indicate serious issues that cannot be addressed through standard error
handling.
When a defect occurs in an effect, the function you provide to this function
will be executed, allowing you to log, monitor, or handle the defect in some
way. Importantly, this does not alter the main result of the effect. If no
defect occurs, the effect behaves as if this function was not used.
@example
import { Effect, Console } from"effect"
// Simulate a task that fails with a recoverable error
Runs an effect in the background, returning a fiber that can be observed or
interrupted.
Unless you specifically need a Promise or synchronous operation, runFork
is a good default choice.
Details
This function is the foundational way to execute an effect in the background.
It creates a "fiber," a lightweight, cooperative thread of execution that can
be observed (to access its result), interrupted, or joined. Fibers are useful
for concurrent programming and allow effects to run independently of the main
program flow.
Once the effect is running in a fiber, you can monitor its progress, cancel
it if necessary, or retrieve its result when it completes. If the effect
fails, the fiber will propagate the failure, which you can observe and
handle.
When to Use
Use this function when you need to run an effect in the background,
especially if the effect is long-running or performs periodic tasks. It's
suitable for tasks that need to run independently but might still need
observation or management, like logging, monitoring, or scheduled tasks.
This function is ideal if you don't need the result immediately or if the
effect is part of a larger concurrent workflow.
The Effect interface defines a value that describes a workflow or job,
which can succeed or fail.
Details
The Effect interface represents a computation that can model a workflow
involving various types of operations, such as synchronous, asynchronous,
concurrent, and parallel interactions. It operates within a context of type
R, and the result can either be a success with a value of type A or a
failure with an error of type E. The Effect is designed to handle complex
interactions with external resources, offering advanced features such as
fiber-based concurrency, scheduling, interruption handling, and scalability.
This makes it suitable for tasks that require fine-grained control over
concurrency and error management.
To execute an Effect value, you need a Runtime, which provides the
environment necessary to run and manage the computation.
Creates an effect that terminates a fiber with a RuntimeException
containing the specified message.
Details
This function is used to signal a defect, representing a critical and
unexpected error in the code. When invoked, it produces an effect that
terminates the fiber with a RuntimeException carrying the given message.
The resulting effect has an error channel of type never, indicating it does
not handle or recover from the error.
When to Use
Use this function when you want to terminate a fiber due to an unrecoverable
defect and include a clear explanation in the message.
@see ― die for a variant that throws a specified error.
@see ― dieSync for a variant that throws a specified error, evaluated
lazily.
@example
// Title: Terminating on Division by Zero with a Specified Message
Inspect severe errors or defects (non-recoverable failures) in an effect.
Details
This function is specifically designed to handle and inspect defects, which
are critical failures in your program, such as unexpected runtime exceptions
or system-level errors. Unlike normal recoverable errors, defects typically
indicate serious issues that cannot be addressed through standard error
handling.
When a defect occurs in an effect, the function you provide to this function
will be executed, allowing you to log, monitor, or handle the defect in some
way. Importantly, this does not alter the main result of the effect. If no
defect occurs, the effect behaves as if this function was not used.
@example
import { Effect, Console } from"effect"
// Simulate a task that fails with a recoverable error
Runs an effect in the background, returning a fiber that can be observed or
interrupted.
Unless you specifically need a Promise or synchronous operation, runFork
is a good default choice.
Details
This function is the foundational way to execute an effect in the background.
It creates a "fiber," a lightweight, cooperative thread of execution that can
be observed (to access its result), interrupted, or joined. Fibers are useful
for concurrent programming and allow effects to run independently of the main
program flow.
Once the effect is running in a fiber, you can monitor its progress, cancel
it if necessary, or retrieve its result when it completes. If the effect
fails, the fiber will propagate the failure, which you can observe and
handle.
When to Use
Use this function when you need to run an effect in the background,
especially if the effect is long-running or performs periodic tasks. It's
suitable for tasks that need to run independently but might still need
observation or management, like logging, monitoring, or scheduled tasks.
This function is ideal if you don't need the result immediately or if the
effect is part of a larger concurrent workflow.
Filters an effect, failing with a custom error if the predicate fails.
Details
This function applies a predicate to the result of an effect. If the
predicate evaluates to false, the effect fails with a custom error
generated by the orFailWith function.
When to Use
This is useful for enforcing constraints and treating violations as
recoverable errors.
Providing a Guard
In addition to the filtering capabilities discussed earlier, you have the
option to further refine and narrow down the type of the success channel by
providing a user-defined type
guard.
Let's explore this concept through an example:
@example
import { Effect, pipe } from"effect"
// Define a user interface
interfaceUser {
readonlyname:string
}
// Simulate an asynchronous authentication function
declareconstauth: () =>Promise<User|null>
constprogram=pipe(
Effect.promise(() =>auth()),
// Use filterOrFail with a custom type guard to ensure user is not null
Effect.filterOrFail(
(user):userisUser=> user !==null, // Type guard
() =>newError("Unauthorized")
),
// 'user' now has the type `User` (not `User | null`)
Allows you to inspect both success and failure outcomes of an effect and
perform side effects for each.
Details
This function enables you to handle both success and failure cases
separately, without modifying the main effect's result. It is particularly
useful for scenarios where you need to log, monitor, or perform additional
actions depending on whether the effect succeeded or failed.
When the effect succeeds, the onSuccess handler is executed with the
success value. When the effect fails, the onFailure handler is executed
with the failure value. Both handlers can include side effects such as
logging or analytics, and neither modifies the original effect's output.
If either the success or failure handler fails, the overall effect will also
fail.
@example
import { Effect, Random, Console } from"effect"
// Simulate a task that might fail
consttask= Effect.filterOrFail(
Random.nextRange(-1, 1),
(n) => n >=0,
() =>"random number is negative"
)
// Use tapBoth to log both success and failure outcomes
Runs an effect in the background, returning a fiber that can be observed or
interrupted.
Unless you specifically need a Promise or synchronous operation, runFork
is a good default choice.
Details
This function is the foundational way to execute an effect in the background.
It creates a "fiber," a lightweight, cooperative thread of execution that can
be observed (to access its result), interrupted, or joined. Fibers are useful
for concurrent programming and allow effects to run independently of the main
program flow.
Once the effect is running in a fiber, you can monitor its progress, cancel
it if necessary, or retrieve its result when it completes. If the effect
fails, the fiber will propagate the failure, which you can observe and
handle.
When to Use
Use this function when you need to run an effect in the background,
especially if the effect is long-running or performs periodic tasks. It's
suitable for tasks that need to run independently but might still need
observation or management, like logging, monitoring, or scheduled tasks.
This function is ideal if you don't need the result immediately or if the
effect is part of a larger concurrent workflow.
The Effect.either function transforms an Effect<A, E, R> into an effect that encapsulates both potential failure and success within an Either data type:
Effect<A, E, R>-> Effect<Either<A, E>, never, R>
This means if you have an effect with the following type:
Effect<string, HttpError, never>
and you call Effect.either on it, the type becomes:
Effect<Either<string, HttpError>, never, never>
The resulting effect cannot fail because the potential failure is now represented within the Either’s Left type.
The error type of the returned Effect is specified as never, confirming that the effect is structured to not fail.
This function becomes especially useful when recovering from effects that may fail when using Effect.gen:
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
.
@see ― succeed to create an effect that represents a successful value.
constas: <number>(value:number) => <A, E, R>(self:Effect.Effect<A, E, R>) =>Effect.Effect<number, E, R> (+1overload)
Replaces the value inside an effect with a constant value.
Details
This function allows you to ignore the original value inside an effect and
replace it with a constant value.
When to Use
It is useful when you no longer need the value produced by an effect but want
to ensure that the effect completes successfully with a specific constant
result instead. For instance, you can replace the value produced by a
computation with a predefined value, ignoring what was calculated before.
@example
// Title: Replacing a Value
import { pipe, Effect } from"effect"
// Replaces the value 5 with the constant "new value"
Provides a way to write effectful code using generator functions, simplifying
control flow and error handling.
When to Use
Effect.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.
Encapsulates both success and failure of an Effect into an Either type.
Details
This function converts an effect that may fail into an effect that always
succeeds, wrapping the outcome in an Either type. The result will be
Either.Left if the effect fails, containing the recoverable error, or
Either.Right if it succeeds, containing the result.
Using this function, you can handle recoverable errors explicitly without
causing the effect to fail. This is particularly useful in scenarios where
you want to chain effects and manage both success and failure in the same
logical flow.
It's important to note that unrecoverable errors, often referred to as
"defects," are still thrown and not captured within the Either type. Only
failures that are explicitly represented as recoverable errors in the effect
are encapsulated.
The resulting effect cannot fail directly because all recoverable failures
are represented inside the Either type.
@see ― option for a version that uses Option instead.
@see ― exit for a version that encapsulates both recoverable errors and defects in an Exit.
Executes an effect and returns the result as a Promise.
Details
This function runs an effect and converts its result into a Promise. If the
effect succeeds, the Promise will resolve with the successful result. If
the effect fails, the Promise will reject with an error, which includes the
failure details of the effect.
The optional options parameter allows you to pass an AbortSignal for
cancellation, enabling more fine-grained control over asynchronous tasks.
When to Use
Use this function when you need to execute an effect and work with its result
in a promise-based system, such as when integrating with third-party
libraries that expect Promise results.
@see ― runPromiseExit for a version that returns an Exit type instead
of rejecting.
@example
// Title: Running a Successful Effect as a Promise
Attaches callbacks for the resolution and/or rejection of the Promise.
@param ― onfulfilled The callback to execute when the Promise is resolved.
@param ― onrejected The callback to execute when the Promise is rejected.
@returns ― A 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(newError('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
constname='Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr
Example using the Console class:
constout=getStreamSomehow();
consterr=getStreamSomehow();
constmyConsole=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(newError('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
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()).
You can use the Effect.cause function to expose the cause of an effect, which is a more detailed representation of failures, including error messages and defects.
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
.
@see ― succeed to create an effect that represents a successful value.
constas: <number>(value:number) => <A, E, R>(self:Effect.Effect<A, E, R>) =>Effect.Effect<number, E, R> (+1overload)
Replaces the value inside an effect with a constant value.
Details
This function allows you to ignore the original value inside an effect and
replace it with a constant value.
When to Use
It is useful when you no longer need the value produced by an effect but want
to ensure that the effect completes successfully with a specific constant
result instead. For instance, you can replace the value produced by a
computation with a predefined value, ignoring what was calculated before.
@example
// Title: Replacing a Value
import { pipe, Effect } from"effect"
// Replaces the value 5 with the constant "new value"
Provides a way to write effectful code using generator functions, simplifying
control flow and error handling.
When to Use
Effect.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.
This function allows you to expose the detailed cause of an effect, which
includes a more precise representation of failures, such as error messages
and defects.
When to Use
This function is helpful when you need to inspect the cause of a failure in
an effect, giving you more information than just the error message. It can be
used to log, handle, or analyze failures in more detail, including
distinguishing between different types of defects (e.g., runtime exceptions,
interruptions, etc.).
Merging the Error Channel into the Success Channel
The Effect.merge function allows you to combine the error channel with the success channel. This results in an effect that never fails; instead, both successes and errors are handled as values in the success channel.
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
.
@see ― succeed to create an effect that represents a successful value.
constas: <number>(value:number) => <A, E, R>(self:Effect.Effect<A, E, R>) =>Effect.Effect<number, E, R> (+1overload)
Replaces the value inside an effect with a constant value.
Details
This function allows you to ignore the original value inside an effect and
replace it with a constant value.
When to Use
It is useful when you no longer need the value produced by an effect but want
to ensure that the effect completes successfully with a specific constant
result instead. For instance, you can replace the value produced by a
computation with a predefined value, ignoring what was calculated before.
@example
// Title: Replacing a Value
import { pipe, Effect } from"effect"
// Replaces the value 5 with the constant "new value"
Combines both success and error channels of an effect into a single outcome.
Details
This function transforms an effect that may fail into one that always returns
a value, where both success and failure outcomes are handled as values in the
success channel.
When to Use
This can be useful when you want to continue execution regardless of the
error type and still capture both successful results and errors as part of
the outcome.
The Effect.flip function allows you to switch the error and success channels of an effect. This means that what was previously a success becomes the error, and vice versa.
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
.
@see ― succeed to create an effect that represents a successful value.
constas: <number>(value:number) => <A, E, R>(self:Effect.Effect<A, E, R>) =>Effect.Effect<number, E, R> (+1overload)
Replaces the value inside an effect with a constant value.
Details
This function allows you to ignore the original value inside an effect and
replace it with a constant value.
When to Use
It is useful when you no longer need the value produced by an effect but want
to ensure that the effect completes successfully with a specific constant
result instead. For instance, you can replace the value produced by a
computation with a predefined value, ignoring what was calculated before.
@example
// Title: Replacing a Value
import { pipe, Effect } from"effect"
// Replaces the value 5 with the constant "new value"
Swaps the success and error channels of an effect.
Details
This function reverses the flow of an effect by swapping its success and
error channels. The success value becomes an error, and the error value
becomes a success.