心智模型与准备
L02 程序即值:Effect<Success, Error, Requirements>
本课目标
- 读三通道类型签名
- 解释 E=never / R=never / Success=never 各自的含义
前置课时尚未完成:L01
可以自行跳转学习,但按顺序推进会更省力;学情分析会把这类缺口归入「前置缺口」。
一个类型,三份契约
Effect<Success, Error, Requirements> 是一份不可变的程序蓝图:成功时产出 Success;可能以 Error 中列出的预期错误失败;需要 Requirements 里的服务才能运行。官方文档常简写成 A / E / R。
类型签名与提取工具
← 代码可左右滑动 →
import { Context, Effect } from "effect"
class Db extends Context.Service<Db, {}>()("Db") {}
declare const program: Effect.Effect<number, Error, Db>
type A = Effect.Success<typeof program> // number
type E = Effect.Error<typeof program> // Error
type R = Effect.Services<typeof program> // Db💡 三个参数都是协变的,组合时会安全地取并集:多个 yield* 的 E 汇成联合类型,R 汇成需求集合。
never 的三种语义
- Error = never:不可能失败(没有 never 类型的值可以构造出来)。
- Requirements = never:不需要任何服务,Context 为空,可以直接 run*。
- Success = never:永不成功返回——要么一直运行,要么最终失败。
💡 概念上像函数,实际上不是
可以把 Effect<A,E,R> 粗略想成 (context: Context<R>) => A | E,但它不是函数:它能描述同步、异步、并发、带资源的计算,并且每个算子都返回新的 Effect 值,原值永不被修改。
交互演练
关键术语
协变
类型参数在组合时可安全地向更宽的类型 widening
Context<R>
以服务键为索引的不可变服务集合
常见误区
× 看到 Success=never 以为是 void——void 是「成功但没有有用信息」,never 是「根本不会成功」。
随堂测验(即时反馈,答题计入掌握度)
Q1Effect<number, never, never> 说明什么?
Q2关于 Effect 值的可变性,正确的是?