Skip to content

Effect 类型

Effect 类型是工作流或操作的不可变描述,它是惰性执行的。这意味着当您创建一个 Effect 时,它不会立即运行,而是定义一个可以成功、失败或需要一些额外上下文才能完成的程序。

以下是 Effect 的一般形式:

┌─── 表示成功类型
│ ┌─── 表示错误类型
│ │ ┌─── 表示所需依赖
▼ ▼ ▼
Effect<Success, Error, Requirements>

此类型表示一个 effect:

  • 成功并返回 Success 类型的值
  • 失败并产生 Error 类型的错误
  • 可能需要 Requirements 类型的某些上下文依赖才能执行

从概念上讲,您可以将 Effect 视为以下函数类型的副作用版本:

type Effect<Success, Error, Requirements> = (
context: Context<Requirements>
) => Error | Success

然而,effect 实际上不是函数。它们可以建模同步、异步、并发和资源型计算。

不可变性。Effect 值是不可变的,Effect 库中的每个函数都会产生一个新的 Effect 值。

建模交互。这些值本身不执行任何操作,它们只是建模或描述副作用交互。

执行。Effect 可以由 Effect 运行时系统 执行,它将其解释为与外部世界的实际交互。 理想情况下,这种执行发生在应用程序的单个入口点,例如启动副作用操作的主函数中。

Effect 类型有三个类型参数,含义如下:

参数描述
Success表示 effect 执行时可以成功返回的值的类型。如果此类型参数是 void,则意味着 effect 不产生有用信息,而如果是 never,则意味着 effect 永远运行(或直到失败)。
Error表示执行 effect 时可能发生的预期错误。如果此类型参数是 never,则意味着 effect 不能失败,因为没有 never 类型的值。
Requirements表示 effect 执行所需的上下文数据。此数据存储在名为 Context 的集合中。如果此类型参数是 never,则意味着 effect 没有需求,Context 集合为空。

通过使用工具类型 Effect.SuccessEffect.ErrorEffect.Context,您可以从 effect 中提取相应的类型。

示例(提取成功、错误和上下文类型)

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
,
import Context

@since2.0.0

@since2.0.0

Context
} from "effect"
class
class SomeContext
SomeContext
extends
import Context

@since2.0.0

@since2.0.0

Context
.
const Tag: <"SomeContext">(id: "SomeContext") => <Self, Shape>() => Context.TagClass<Self, "SomeContext", Shape>

@example

import * as assert from "node:assert"
import { Context, Layer } from "effect"
class MyTag extends Context.Tag("MyTag")<
MyTag,
{ readonly myNum: number }
>() {
static Live = Layer.succeed(this, { myNum: 108 })
}

@since2.0.0

Tag
("SomeContext")<
class SomeContext
SomeContext
, {}>() {}
// 假设我们有一个成功返回数字、
// 失败返回 Error、并需要 SomeContext 的 effect
declare const
const program: Effect.Effect<number, Error, SomeContext>
program
:
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
,
class SomeContext
SomeContext
>
// 提取成功类型,即 number
type
type A = number
A
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
namespace Effect

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
.
type Effect<out A, out E = never, out R = never>.Success<T extends Effect.Effect<any, any, any>> = [T] extends [Effect.Effect<infer _A, infer _E, infer _R>] ? _A : never

@since2.0.0

Success
<typeof
const program: Effect.Effect<number, Error, SomeContext>
program
>
// 提取错误类型,即 Error
type
type E = Error
E
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
namespace Effect

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
.
type Effect<out A, out E = never, out R = never>.Error<T extends Effect.Effect<any, any, any>> = [T] extends [Effect.Effect<infer _A, infer _E, infer _R>] ? _E : never

@since2.0.0

Error
<typeof
const program: Effect.Effect<number, Error, SomeContext>
program
>
// 提取上下文类型,即 SomeContext
type
type R = SomeContext
R
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
namespace Effect

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
.
type Effect<out A, out E = never, out R = never>.Context<T extends Effect.Effect<any, any, any>> = [T] extends [Effect.Effect<infer _A, infer _E, infer _R>] ? _R : never

@since2.0.0

Context
<typeof
const program: Effect.Effect<number, Error, SomeContext>
program
>