Effect 类型
理解 Effect 生态中的 Effect 类型:它为带 effect 的计算提供类型安全的成功值、错误与需求处理,并用于建模不可变、惰性的工作流。
Effect 类型是对惰性执行的工作流或操作的描述。也就是说,当你创建一个 Effect 时,它并不会立即运行,而是定义了一个可能成功、失败,或者需要一些额外上下文才能完成的程序。
下面是 Effect 的一般形式:
┌─── Represents the success type
│ ┌─── Represents the error type
│ │ ┌─── Represents required dependencies
▼ ▼ ▼
Effect<Success, Error, Requirements>
这个类型表明一个 effect 会:
- 成功并返回一个
Success类型的值 - 以
Error类型的错误失败 - 执行时可能需要
Requirements类型的特定上下文依赖
从概念上讲,你可以把 Effect 看作下面这种函数类型的「带 effect」版本:
type Effect<Success, Error, Requirements> = (
context: Context<Requirements>,
) => Error | Success
不过,effect 实际上并不是函数。它们可以建模同步、异步、并发以及需要管理资源的计算。
不可变性。Effect 值是不可变的,Effect 库中的每个函数都会产生一个新的 Effect 值。
对交互建模。这些值本身不执行任何动作,它们只是建模或描述带 effect 的交互。
执行。Effect 可以由 Effect 运行时系统 执行,后者会把它解释为与外部世界的实际交互。
理想情况下,这次执行发生在你应用中的单一入口点,例如发起各种 effect 操作的 main 函数。
类型参数
Effect 类型有三个类型参数,含义如下:
| 参数 | 说明 |
|---|---|
| Success | 表示 effect 执行成功时所产生的值的类型。如果该类型参数是 void,说明这个 effect 不产生任何有用的信息;如果它是 never,说明这个 effect 会永远运行下去(或者直到失败)。 |
| Error | 表示执行 effect 时可能发生的预期错误。如果该类型参数是 never,说明这个 effect 不会失败,因为不存在 never 类型的值。 |
| Requirements | 表示 effect 执行所需的上下文数据。这些数据存储在一个名为 Context 的集合中。如果该类型参数是 never,说明这个 effect 没有任何需求,Context 集合是空的。 |
在 Effect 生态中,你经常会遇到 Effect 的类型参数被分别简写为 A、E 和 R。这只是成功值类型 A、Error 和 Requirements 的简写。
提取推断出的类型
借助工具类型 Effect.Success、Effect.Error 和 Effect.Context,你可以从一个 effect 中提取出相应的类型。
示例(提取 Success、Error 与 Context 类型)
import { Effect, Context } from "effect"
class SomeContext extends Context.Tag("SomeContext")<SomeContext, {}>() {}
// Assume we have an effect that succeeds with a number,
// fails with an Error, and requires SomeContext
declare const program: Effect.Effect<number, Error, SomeContext>
// Extract the success type, which is number
type A = Effect.Effect.Success<typeof program>
// Extract the error type, which is Error
type E = Effect.Effect.Error<typeof program>
// Extract the context type, which is SomeContext
type R = Effect.Effect.Context<typeof program>