Skip to content

创建 Effect

Effect 提供了不同的方式来创建 effect,它们是封装副作用的计算单元。 在本指南中,我们将介绍一些您可以用来创建 effect 的常见方法。

在传统编程中,当发生错误时,通常通过抛出异常来处理:

// 类型签名不显示可能的异常
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
}

然而,抛出错误可能会有问题。函数的类型签名不会指示它们可能抛出异常,这使得推理潜在错误变得困难。

为了解决这个问题,Effect 引入了专用的构造函数来创建表示成功和失败的 effect:Effect.succeedEffect.fail。这些构造函数允许您显式处理成功和失败情况,同时利用类型系统来跟踪错误

创建一个总是成功并返回给定值的 Effect。

当您需要一个成功完成并返回特定值的 effect 时使用此函数, 无需任何错误或外部依赖。

示例(创建成功的 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.

Example (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)

@seefail to create an effect that represents a failure.

@since2.0.0

succeed
(42)

success 的类型是 Effect<number, never, never>,这意味着:

  • 它产生一个 number 类型的值。
  • 它不产生任何错误(never 表示没有错误)。
  • 它不需要任何额外的数据或依赖(never 表示没有需求)。
┌─── 产生 number 类型的值
│ ┌─── 不产生任何错误
│ │ ┌─── 不需要依赖
▼ ▼ ▼
Effect<number, never, never>

创建一个表示可以恢复的错误的 Effect。

使用此函数在 Effect 中显式发出错误信号。错误 将继续传播,除非被处理。您可以使用 Effect.catchAllEffect.catchTag 等函数来处理错误。

示例(创建失败的 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

.

Example (Creating a Failed Effect)

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

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

@since2.0.0

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

failure 的类型是 Effect<never, Error, never>,这意味着:

  • 它永远不会产生值(never 表示不会产生成功结果)。
  • 它失败并产生错误,特别是 Error
  • 它不需要任何额外的数据或依赖(never 表示没有需求)。
┌─── 永远不产生值
│ ┌─── 失败并产生 Error
│ │ ┌─── 不需要依赖
▼ ▼ ▼
Effect<never, Error, never>

虽然您可以在 Effect.fail 中使用 Error 对象,但您也可以根据错误管理策略传递字符串、数字或更复杂的对象。

使用”标记”错误(具有 _tag 字段的对象)可以帮助识别错误类型,并与标准 Effect 函数(如 Effect.catchTag)配合良好。

示例(使用标记错误)

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
,
import Data
Data
} from "effect"
class
class HttpError
HttpError
extends
import Data
Data
.
const TaggedError: <"HttpError">(tag: "HttpError") => new <A>(args: Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => YieldableError & {
readonly _tag: "HttpError";
} & Readonly<A>

@since2.0.0

TaggedError
("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

.

Example (Creating a Failed Effect)

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

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

@since2.0.0

fail
(new
constructor HttpError<{}>(args: void): HttpError
HttpError
())

使用 Effect.succeedEffect.fail,您可以显式处理成功和失败情况,类型系统将确保错误被跟踪和考虑。

示例(重写除法函数)

以下是如何使用 Effect 重写 divide 函数,使错误处理变得显式。

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

@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

.

Example (Creating a Failed Effect)

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

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

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

Example (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)

@seefail to create an effect that represents a failure.

@since2.0.0

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

在此示例中,divide 函数在其返回类型 Effect<number, Error> 中指示操作可以成功返回 number 或失败返回 Error

┌─── 产生 number 类型的值
│ ┌─── 失败并产生 Error
▼ ▼
Effect<number, Error>

这个清晰的类型签名有助于确保错误得到正确处理,并且调用函数的任何人都知道可能的结果。

示例(模拟用户检索操作)

让我们想象另一个场景,我们使用 Effect.succeedEffect.fail 来建模一个简单的用户检索操作,其中用户数据是硬编码的,这在测试场景或模拟数据时可能很有用:

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
} from "effect"
// 定义 User 类型
interface
interface User
User
{
readonly
User.id: number
id
: number
readonly
User.name: string
name
: string
}
// 模拟从数据库获取用户的函数
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 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.

@since2.0.0

@since2.0.0

Effect
<
interface User
User
,
interface Error
Error
> => {
// 通常,您会在这里访问数据库或 API,但我们将模拟它
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" }
}
// 检查用户是否存在于我们的"数据库"中并适当返回
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.

Example (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)

@seefail to create an effect that represents a failure.

@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

.

Example (Creating a Failed Effect)

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

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

@since2.0.0

fail
(new
var Error: ErrorConstructor
new (message?: string) => Error
Error
("User not found"))
}
}
// 执行时,这将成功返回 id 为 1 的用户
const
const exampleUserEffect: Effect.Effect<User, Error, never>
exampleUserEffect
=
const getUser: (userId: number) => Effect.Effect<User, Error>
getUser
(1)

在此示例中,exampleUserEffect 的类型为 Effect<User, Error>,将根据用户是否存在于模拟数据库中产生 User 对象或 Error

要深入了解应用程序中的错误管理,请参阅错误管理指南

在 JavaScript 中,您可以使用”thunk”来延迟同步计算的执行。

Thunk 对于延迟值的计算直到需要时才执行很有用。

为了建模同步副作用,Effect 提供了 Effect.syncEffect.try 构造函数,它们接受一个 thunk。

创建一个表示同步副作用计算的 Effect。

当您确定操作不会失败时使用 Effect.sync

提供的函数(thunk)不得抛出错误;如果抛出,错误将被视为”缺陷”

这种缺陷不是标准错误,而是表示预期无错误的逻辑中的缺陷。 您可以将其视为程序中的意外崩溃,可以使用 Effect.catchAllDefect 等工具进一步管理或记录。 此功能确保应用程序中的意外失败不会丢失,并且可以得到适当处理。

示例(记录消息)

在下面的示例中,Effect.sync 用于延迟写入控制台的副作用。

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.

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

.

When to Use

Use this function when you are sure the operation will not fail.

Example (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!")

@seetry_try for a version that can handle failures.

@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
) // 副作用
})
// ┌─── 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!")

封装在 program 中的副作用(记录到控制台)直到 effect 被显式运行才会发生(有关更多详细信息,请参阅运行 Effect 部分)。这允许您在代码的一个点定义副作用,并控制何时激活它们,从而提高大型应用程序中副作用的可管理性和可预测性。

创建一个表示可能失败的同步计算的 Effect。

在需要执行可能失败的同步操作(如解析 JSON)的情况下,您可以使用 Effect.try 构造函数。 此构造函数旨在通过捕获可能抛出异常的操作并将其转换为可管理的错误来处理这些操作。

示例(安全的 JSON 解析)

假设您有一个尝试解析 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) =>
// 如果输入不是有效的 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.

@throws{SyntaxError} If text is not valid JSON.

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
("")

在此示例中:

  • parse 是一个创建封装 JSON 解析操作的 effect 的函数。
  • 如果 JSON.parse(input) 由于无效输入而抛出错误,Effect.try 会捕获此错误,program 表示的 effect 将失败并产生 UnknownException。这确保错误不会被静默忽略,而是在 effect 的结构化流程中处理。

您可能希望将捕获的异常转换为更具体的错误,或在捕获错误时执行其他操作。Effect.try 支持一个重载,允许您指定如何转换捕获的异常:

示例(自定义错误处理)

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 可能因错误输入而抛出异常
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.

@throws{SyntaxError} If text is not valid JSON.

parse
(
input: string
input
),
// 重新映射错误
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
("")

您可以将此视为与 JavaScript 中传统 try-catch 块类似的模式:

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

在传统编程中,我们经常使用 Promise 来处理异步计算。然而,在 promise 中处理错误可能会有问题。默认情况下,Promise<Value> 只为解析值提供类型 Value,这意味着错误不会反映在类型系统中。这限制了表达能力,并使有效处理和跟踪错误变得困难。

为了克服这些限制,Effect 引入了专用的构造函数来创建在异步上下文中表示成功和失败的 effect:Effect.promiseEffect.tryPromise。这些构造函数允许您显式处理成功和失败情况,同时利用类型系统来跟踪错误

创建一个表示保证成功的异步计算的 Effect。

当您确定操作不会被拒绝时使用 Effect.promise

提供的函数(thunk)返回一个永远不应该被拒绝的 Promise;如果被拒绝,错误将被视为”缺陷”

这种缺陷不是标准错误,而是表示预期无错误的逻辑中的缺陷。 您可以将其视为程序中的意外崩溃,可以使用 Effect.catchAllDefect 等工具进一步管理或记录。 此功能确保应用程序中的意外失败不会丢失,并且可以得到适当处理。

示例(延迟消息)

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.

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.

Example (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!")

@seetryPromise for a version that can handle failures.

@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, delay?: 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 or NaN, 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. Default: 1.

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

@returnsfor use with clearTimeout()

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!")

program 值的类型为 Effect<string, never, never>,可以解释为一个 effect:

  • 成功返回 string 类型的值
  • 不产生任何预期错误(never
  • 不需要任何上下文(never

创建一个表示可能失败的异步计算的 Effect。

Effect.promise 不同,当底层 Promise 可能被拒绝时,此构造函数是合适的。 它提供了一种捕获错误并适当处理它们的方法。 默认情况下,如果发生错误,它将被捕获并作为 UnknownException 传播到错误通道。

示例(获取 TODO 项目)

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) =>
// 将捕获任何错误并将其作为 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.

Example (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 (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)

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

@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)

program 值的类型为 Effect<Response, UnknownException, never>,可以解释为一个 effect:

  • 成功返回 Response 类型的值
  • 可能产生错误(UnknownException
  • 不需要任何上下文(never

如果您想更好地控制传播到错误通道的内容,可以使用接受重新映射函数的 Effect.tryPromise 重载:

示例(自定义错误处理)

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<Response, Error, 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.

Example (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 (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)

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

@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
}`),
// 重新映射错误
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)

从基于回调的异步函数创建 Effect。

有时您必须使用不支持 async/awaitPromise 而使用回调风格的 API。 为了处理基于回调的 API,Effect 提供了 Effect.async 构造函数。

示例(包装回调 API)

让我们将 Node.js 的 fs 模块中的 readFile 函数包装成基于 Effect 的 API(确保安装了 @types/node):

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<void, never, never>, blockingOn?: FiberId) => Effect.Effect<Buffer<ArrayBufferLike>, Error, never>

Creates an Effect from a callback-based asynchronous function.

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.

When to Use

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

Example (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 (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 (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: NonSharedBuffer) => 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: NonSharedBuffer
data
) => {
if (
error: NodeJS.ErrnoException | null
error
) {
// 如果发生错误,使用失败的 Effect 恢复
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

.

Example (Creating a Failed Effect)

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

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

@since2.0.0

fail
(
error: NodeJS.ErrnoException
error
))
} else {
// 如果成功,使用成功的 Effect 恢复
resume: (_: Effect.Effect<Buffer<ArrayBufferLike>, Error, never>) => void
resume
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const succeed: <NonSharedBuffer>(value: NonSharedBuffer) => Effect.Effect<NonSharedBuffer, 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.

Example (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)

@seefail to create an effect that represents a failure.

@since2.0.0

succeed
(
data: NonSharedBuffer
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")

在上面的示例中,我们在调用 Effect.async 时手动注释类型:

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

因为 TypeScript 无法基于回调体内的返回值推断回调的类型参数。注释类型确保提供给 resume 的值与预期类型匹配。

Effect.async 内的 resume 函数应该被调用恰好一次。多次调用将导致额外的调用被忽略。

示例(忽略后续的 resume 调用)

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<number, never, never>

Creates an Effect from a callback-based asynchronous function.

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.

When to Use

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

Example (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 (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 (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.

Example (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)

@seefail to create an effect that represents a failure.

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

Example (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)

@seefail to create an effect that represents a failure.

@since2.0.0

succeed
(2)) // 这一行将被忽略
})
// 运行程序
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;
} | undefined) => Promise<number>

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.

Example (Running a Successful Effect as a Promise)

import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

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

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

@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<void>

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
) // 输出:1

对于更高级的用例,resume 可以选择性地返回一个 Effect,如果运行此 effect 的纤程被中断,该 Effect 将被执行。这在需要处理操作被中断时的资源清理的场景中很有用。

示例(使用清理处理中断)

在此示例中:

  • writeFileWithCleanup 函数将数据写入文件。
  • 如果运行此 effect 的纤程被中断,清理 effect(删除文件)将被执行。
  • 这确保在操作被取消时,像打开的文件句柄这样的资源得到正确清理。
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"
// 模拟写入文件的长时间运行操作
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<void, Error, never>

Creates an Effect from a callback-based asynchronous function.

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.

When to Use

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

Example (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 (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 (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
)
// 开始将数据写入文件
const writeStream: NodeFS.WriteStream
writeStream
.
Stream.Writable.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
)
// 当流完成时,使用成功恢复
const writeStream: NodeFS.WriteStream
writeStream
.
WriteStream.on<"finish">(event: "finish", listener: () => void): NodeFS.WriteStream

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

Represents an effect that does nothing and produces no value.

When to Use

Use this effect when you need to represent an effect that does nothing. This is useful in scenarios where you need to satisfy an effect-based interface or control program flow without performing any operations. For example, it can be used in situations where you want to return an effect from a function but do not need to compute or return any result.

@since2.0.0

void
))
// 如果写入过程中发生错误,使用失败恢复
const writeStream: NodeFS.WriteStream
writeStream
.
WriteStream.on<"error">(event: "error", listener: (err: Error) => void): NodeFS.WriteStream

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

.

Example (Creating a Failed Effect)

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

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

@since2.0.0

fail
(
err: Error
err
)))
// 通过返回清理 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.

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

.

When to Use

Use this function when you are sure the operation will not fail.

Example (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!")

@seetry_try for a version that can handle failures.

@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<void, never, never> (+1 overload)

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.

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>

Creates a new fiber to run an effect concurrently.

Details

This function takes an effect and forks it into a separate fiber, allowing it to run concurrently without blocking the original effect. The new fiber starts execution immediately after being created, and the fiber object is returned immediately without waiting for the effect to begin. This is useful when you want to run tasks concurrently while continuing other tasks in the parent fiber.

The forked fiber is attached to the parent fiber's scope. This means that when the parent fiber terminates, the child fiber will also be terminated automatically. This feature, known as "auto supervision," ensures that no fibers are left running unintentionally. If you prefer not to have this auto supervision behavior, you can use

forkDaemon

or

forkIn

.

When to Use

Use this function when you need to run an effect concurrently without blocking the current execution flow. For example, you might use it to launch background tasks or concurrent computations. However, working with fibers can be complex, so before using this function directly, you might want to explore higher-level functions like

raceWith

,

zip

, or others that can manage concurrency for you.

Example

import { Effect } from "effect"
const fib = (n: number): Effect.Effect<number> =>
n < 2
? Effect.succeed(n)
: Effect.zipWith(fib(n - 1), fib(n - 2), (a, b) => a + b)
// ┌─── Effect<RuntimeFiber<number, never>, never, never>
// ▼
const fib10Fiber = Effect.fork(fib(10))

@seeforkWithErrorHandler for a version that allows you to handle errors.

@since2.0.0

fork
(
const writeFileWithCleanup: (filename: string, data: string) => Effect.Effect<void, Error, never>
writeFileWithCleanup
("example.txt", "Some long data...")
)
// 模拟在 1 秒后中断纤程
yield*
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

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

Suspends the execution of an effect for a specified Duration.

Details

This function pauses the execution of an effect for a given duration. It is asynchronous, meaning that it does not block the fiber executing the effect. Instead, the fiber is suspended during the delay period and can resume once the specified time has passed.

The duration can be specified using various formats supported by the Duration module, such as a string ("2 seconds") or numeric value representing milliseconds.

Example

import { Effect } from "effect"
const program = Effect.gen(function*() {
console.log("Starting task...")
yield* Effect.sleep("3 seconds") // Waits for 3 seconds
console.log("Task completed!")
})
Effect.runFork(program)
// Output:
// Starting task...
// Task completed!

@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
) // 这将触发清理
})
// 运行程序
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;
} | undefined) => Promise<void>

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.

Example (Running a Successful Effect as a Promise)

import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

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

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

@since2.0.0

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

如果您包装的操作支持中断,resume 函数可以接收 AbortSignal 来直接处理中断请求。

示例(使用 AbortSignal 处理中断)

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
,
import Fiber
Fiber
} from "effect"
// 支持使用 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<void, Error, never>

Creates an Effect from a callback-based asynchronous function.

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.

When to Use

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

Example (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 (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 (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
) => {
// 处理中断
signal: AbortSignal
signal
.
EventTarget.addEventListener(type: string, listener: EventListener | EventListenerObject, options?: AddEventListenerOptions | boolean): void
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(timeout: 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
)
})
// 模拟长时间运行的任务
const
const timeoutId: NodeJS.Timeout
timeoutId
=
function setTimeout<[]>(callback: () => void, delay?: 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 or NaN, 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. Default: 1.

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

@returnsfor use with clearTimeout()

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

Represents an effect that does nothing and produces no value.

When to Use

Use this effect when you need to represent an effect that does nothing. This is useful in scenarios where you need to satisfy an effect-based interface or control program flow without performing any operations. For example, it can be used in situations where you want to return an effect from a function but do not need to compute or return any result.

@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<void, never, never> (+1 overload)

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.

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>

Creates a new fiber to run an effect concurrently.

Details

This function takes an effect and forks it into a separate fiber, allowing it to run concurrently without blocking the original effect. The new fiber starts execution immediately after being created, and the fiber object is returned immediately without waiting for the effect to begin. This is useful when you want to run tasks concurrently while continuing other tasks in the parent fiber.

The forked fiber is attached to the parent fiber's scope. This means that when the parent fiber terminates, the child fiber will also be terminated automatically. This feature, known as "auto supervision," ensures that no fibers are left running unintentionally. If you prefer not to have this auto supervision behavior, you can use

forkDaemon

or

forkIn

.

When to Use

Use this function when you need to run an effect concurrently without blocking the current execution flow. For example, you might use it to launch background tasks or concurrent computations. However, working with fibers can be complex, so before using this function directly, you might want to explore higher-level functions like

raceWith

,

zip

, or others that can manage concurrency for you.

Example

import { Effect } from "effect"
const fib = (n: number): Effect.Effect<number> =>
n < 2
? Effect.succeed(n)
: Effect.zipWith(fib(n - 1), fib(n - 2), (a, b) => a + b)
// ┌─── Effect<RuntimeFiber<number, never>, never, never>
// ▼
const fib10Fiber = Effect.fork(fib(10))

@seeforkWithErrorHandler for a version that allows you to handle errors.

@since2.0.0

fork
(
const interruptibleTask: Effect.Effect<void, Error, never>
interruptibleTask
)
// 模拟在 1 秒后中断纤程
yield*
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

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

Suspends the execution of an effect for a specified Duration.

Details

This function pauses the execution of an effect for a given duration. It is asynchronous, meaning that it does not block the fiber executing the effect. Instead, the fiber is suspended during the delay period and can resume once the specified time has passed.

The duration can be specified using various formats supported by the Duration module, such as a string ("2 seconds") or numeric value representing milliseconds.

Example

import { Effect } from "effect"
const program = Effect.gen(function*() {
console.log("Starting task...")
yield* Effect.sleep("3 seconds") // Waits for 3 seconds
console.log("Task completed!")
})
Effect.runFork(program)
// Output:
// Starting task...
// Task completed!

@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
)
})
// 运行程序
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;
} | undefined) => Promise<void>

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.

Example (Running a Successful Effect as a Promise)

import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

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

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

@since2.0.0

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

Effect.suspend 用于延迟 effect 的创建。 它允许您延迟 effect 的评估,直到实际需要时才执行。 Effect.suspend 函数接受一个表示 effect 的 thunk,并将其包装在悬挂的 effect 中。

语法

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

让我们探索一些 Effect.suspend 证明有用的常见场景。

当您想要延迟 effect 的评估直到需要时。这对于优化 effect 的执行很有用,特别是当它们并不总是需要或计算成本很高时。

此外,当创建具有副作用或作用域捕获的 effect 时,使用 Effect.suspend 在每次调用时重新执行。

示例(具有副作用的惰性求值)

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.

Example (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)

@seefail to create an effect that represents a failure.

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

Details

The Effect.suspend function 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.

When to Use

Use this function 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.

Example (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 (Recursive Fibonacci)

import { Effect } from "effect"
const blowsUp = (n: number): Effect.Effect<number> =>
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<number> =>
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 (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.

Example (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)

@seefail to create an effect that represents a failure.

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

Details

This function evaluates the provided effect synchronously, returning its result directly. It is ideal for effects that do not fail or include asynchronous operations. If the effect does fail or involves async tasks, it will throw an error. Execution stops at the point of failure or asynchronous operation, making it unsuitable for effects that require asynchronous handling.

Important: Attempting to run effects that involve asynchronous operations or failures will result in exceptions being thrown, so use this function with care for purely synchronous and error-free effects.

When to Use

Use this function when:

  • You are sure that the effect will not fail or involve asynchronous operations.
  • You need a direct, synchronous result from the effect.
  • You are working within a context where asynchronous effects are not allowed.

Avoid using this function for effects that can fail or require asynchronous handling. For such cases, consider using

runPromise

or

runSyncExit

.

Example (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 (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

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

@since2.0.0

runSync
(
const bad: Effect.Effect<number, never, never>
bad
)) // 输出: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.

Details

This function evaluates the provided effect synchronously, returning its result directly. It is ideal for effects that do not fail or include asynchronous operations. If the effect does fail or involves async tasks, it will throw an error. Execution stops at the point of failure or asynchronous operation, making it unsuitable for effects that require asynchronous handling.

Important: Attempting to run effects that involve asynchronous operations or failures will result in exceptions being thrown, so use this function with care for purely synchronous and error-free effects.

When to Use

Use this function when:

  • You are sure that the effect will not fail or involve asynchronous operations.
  • You need a direct, synchronous result from the effect.
  • You are working within a context where asynchronous effects are not allowed.

Avoid using this function for effects that can fail or require asynchronous handling. For such cases, consider using

runPromise

or

runSyncExit

.

Example (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 (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

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

@since2.0.0

runSync
(
const bad: Effect.Effect<number, never, never>
bad
)) // 输出: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.

Details

This function evaluates the provided effect synchronously, returning its result directly. It is ideal for effects that do not fail or include asynchronous operations. If the effect does fail or involves async tasks, it will throw an error. Execution stops at the point of failure or asynchronous operation, making it unsuitable for effects that require asynchronous handling.

Important: Attempting to run effects that involve asynchronous operations or failures will result in exceptions being thrown, so use this function with care for purely synchronous and error-free effects.

When to Use

Use this function when:

  • You are sure that the effect will not fail or involve asynchronous operations.
  • You need a direct, synchronous result from the effect.
  • You are working within a context where asynchronous effects are not allowed.

Avoid using this function for effects that can fail or require asynchronous handling. For such cases, consider using

runPromise

or

runSyncExit

.

Example (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 (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

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

@since2.0.0

runSync
(
const good: Effect.Effect<number, never, never>
good
)) // 输出: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.

Details

This function evaluates the provided effect synchronously, returning its result directly. It is ideal for effects that do not fail or include asynchronous operations. If the effect does fail or involves async tasks, it will throw an error. Execution stops at the point of failure or asynchronous operation, making it unsuitable for effects that require asynchronous handling.

Important: Attempting to run effects that involve asynchronous operations or failures will result in exceptions being thrown, so use this function with care for purely synchronous and error-free effects.

When to Use

Use this function when:

  • You are sure that the effect will not fail or involve asynchronous operations.
  • You need a direct, synchronous result from the effect.
  • You are working within a context where asynchronous effects are not allowed.

Avoid using this function for effects that can fail or require asynchronous handling. For such cases, consider using

runPromise

or

runSyncExit

.

Example (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 (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

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

@since2.0.0

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

在此示例中,bad 是调用 Effect.succeed(i++) 一次的结果,它递增作用域变量但返回其原始值Effect.runSync(bad) 不会导致任何新的计算,因为 Effect.succeed(i++) 已经被调用过了。另一方面,每次调用 Effect.runSync(good) 时,传递给 Effect.suspend() 的 thunk 都会被执行,输出作用域变量的最新值。

Effect.suspend 在管理 effect 之间的循环依赖时很有帮助,其中一个 effect 依赖于另一个,反之亦然。 例如,在递归函数中使用 Effect.suspend 来避免急切调用是相当常见的。

示例(递归斐波那契)

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

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

Example (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)

@seefail to create an effect that represents a failure.

@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<number, never, never> (+1 overload)

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

Details

This function runs two effects in sequence (or concurrently, if the { concurrent: true } option is provided) and combines their results using a provided function. Unlike

zip

, which returns a tuple of the results, this function processes the results with a custom function to produce a single output.

Example (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)))
// 崩溃:JavaScript 堆内存不足
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 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.

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

Example (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)

@seefail to create an effect that represents a failure.

@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<number, never, never> (+1 overload)

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

Details

This function runs two effects in sequence (or concurrently, if the { concurrent: true } option is provided) and combines their results using a provided function. Unlike

zip

, which returns a tuple of the results, this function processes the results with a custom function to produce a single output.

Example (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.

Details

The Effect.suspend function 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.

When to Use

Use this function 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.

Example (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 (Recursive Fibonacci)

import { Effect } from "effect"
const blowsUp = (n: number): Effect.Effect<number> =>
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<number> =>
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 (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.

Details

The Effect.suspend function 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.

When to Use

Use this function 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.

Example (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 (Recursive Fibonacci)

import { Effect } from "effect"
const blowsUp = (n: number): Effect.Effect<number> =>
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<number> =>
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 (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.

Details

This function evaluates the provided effect synchronously, returning its result directly. It is ideal for effects that do not fail or include asynchronous operations. If the effect does fail or involves async tasks, it will throw an error. Execution stops at the point of failure or asynchronous operation, making it unsuitable for effects that require asynchronous handling.

Important: Attempting to run effects that involve asynchronous operations or failures will result in exceptions being thrown, so use this function with care for purely synchronous and error-free effects.

When to Use

Use this function when:

  • You are sure that the effect will not fail or involve asynchronous operations.
  • You need a direct, synchronous result from the effect.
  • You are working within a context where asynchronous effects are not allowed.

Avoid using this function for effects that can fail or require asynchronous handling. For such cases, consider using

runPromise

or

runSyncExit

.

Example (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 (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

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

@since2.0.0

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

blowsUp 函数创建递归斐波那契序列而不延迟执行。每次调用 blowsUp 都会触发进一步的立即递归调用,迅速增加 JavaScript 调用栈大小。

相反,allGood 通过使用 Effect.suspend 延迟递归调用来避免栈溢出。这种机制不会立即执行递归 effect,而是安排它们稍后运行,从而保持调用栈浅层并防止崩溃。

在 TypeScript 难以统一返回的 effect 类型的情况下,可以使用 Effect.suspend 来解决这个问题。

示例(使用 Effect.suspend 帮助 TypeScript 推断类型)

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
} from "effect"
/*
没有 suspend,TypeScript 可能在类型推断上有困难。
推断类型:
(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

.

Example (Creating a Failed Effect)

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

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

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

Example (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)

@seefail to create an effect that represents a failure.

@since2.0.0

succeed
(
a: number
a
/
b: number
b
)
/*
使用 suspend 来统一返回类型。
推断类型:
(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.

Details

The Effect.suspend function 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.

When to Use

Use this function 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.

Example (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 (Recursive Fibonacci)

import { Effect } from "effect"
const blowsUp = (n: number): Effect.Effect<number> =>
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<number> =>
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 (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

.

Example (Creating a Failed Effect)

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

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

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

Example (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)

@seefail to create an effect that represents a failure.

@since2.0.0

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

该表提供了可用构造函数的摘要,以及它们的输入和输出类型,允许您根据需要选择适当的函数。

API给定结果
succeedAEffect<A>
failEEffect<never, E>
sync() => AEffect<A>
try() => AEffect<A, UnknownException>
try(重载)() => A, unknown => EEffect<A, E>
promise() => Promise<A>Effect<A>
tryPromise() => Promise<A>Effect<A, UnknownException>
tryPromise(重载)() => Promise<A>, unknown => EEffect<A, E>
async(Effect<A, E> => void) => voidEffect<A, E>
suspend() => Effect<A, E, R>Effect<A, E, R>

有关构造函数的完整列表,请访问 Effect 构造函数文档