Effect 4.0 新增 API 深度解析:Effect.catchNoSuchElement 与 NoSuchElementError 的 Option 化转换
Effect 4.0 新增 API 深度解析Effect.catchNoSuchElement 与 NoSuchElementError 的 Option 化转换【免费下载链接】t3code项目地址: https://gitcode.com/GitHub_Trending/t3/t3code本文围绕 effect-smol 仓库 changeset tall-mails-listen.md 宣告的新增 APIEffect.catchNoSuchElement展开讲解它是 v3Effect.optionFromOptional的重命名移植版本如何将NoSuchElementError类型化失败转换为Option.none成功值。读完本文你将掌握该 API 的类型签名、内部实现原理、典型使用场景以及它与fromOption、fromNullishOr、option等错误处理原语的边界划分。变更公告一次重命名移植在 .changeset/pre/tall-mails-listen.md 中记录了如下变更--- effect: patch --- Add Effect.catchNoSuchElement, a renamed port of v3 Effect.optionFromOptional that converts NoSuchElementError failures into Option.none.这条 changeset 包含三个关键信息包与版本影响变更作用于effect包版本类型为patch不破坏既有 API仅新增导出定位它是 v3 时代Effect.optionFromOptional的重命名移植renamed port而非全新设计核心语义将NoSuchElementError类型的失败转换为Option.none成功值。仓库的 CHANGELOG.md 中对应条目PR #1298commit8f663bb给出了完全一致的描述可作为该变更的官方背书。类型签名从错误通道中剔除 NoSuchElementErrorcatchNoSuchElement的公开类型定义位于 packages/effect/src/Effect.ts#L3448-L3450export const catchNoSuchElement: A, E, R( self: EffectA, E, R ) EffectOptionA, ExcludeE, Cause.NoSuchElementError, R internal.catchNoSuchElement逐个解读三个类型参数的变化通道变换前变换后说明成功值AAOptionA成功值被包装进Option.some错误EE可能含NoSuchElementErrorExcludeE, Cause.NoSuchElementError从类型层面剔除NoSuchElementError环境RRR环境需求不变Exclude意味着如果E中同时存在NoSuchElementError与其他错误类型转换后错误通道只保留其他错误如果NoSuchElementError是唯一错误类型那么错误通道会退化为never——这一点在类型测试中有专门验证见下文类型层面保证一节。该 API 标记为since 4.0.0归类于category error handling错误处理并与三个相关 API 建立交叉引用Effect.ts#L3441-L3443see fromOption—— 将Option.none反转为NoSuchElementErrorsee fromNullishOr—— 将 nullish 值反转为NoSuchElementErrorsee option—— 将任何失败都转换为Option.none。内部实现一次 matchEffect 分发catchNoSuchElement的实现位于 packages/effect/src/internal/effect.ts#L2574-L2584/** internal */ export const catchNoSuchElement A, E, R( self: Effect.EffectA, E, R ): Effect.EffectOption.OptionA, ExcludeE, Cause.NoSuchElementError, R matchEffect(self, { onFailure: (error) isNoSuchElementError(error) ? succeedNone : fail(error as ExcludeE, Cause.NoSuchElementError), onSuccess: succeedSome })实现逻辑非常直观仅需理解三点matchEffect分发对原 Effect 的成功与失败两种结局分别处理isNoSuchElementError类型守卫失败分支先用 Cause.isNoSuchElementError 判定错误是否为NoSuchElementError。是则返回succeedNone成功值为Option.none的 Effect否则原样fail透传成功分支包装任何成功值a都会被包装为succeedSome(a)即Option.some(a)。从源码结构可以推断该函数内部直接复用了仓库中已有的matchEffect、succeedNone、succeedSome等基础原语因此实现极薄、无额外分配开销语义与公开文档完全一致。NoSuchElementError被精确捕获的目标错误catchNoSuchElement只针对NoSuchElementError这一种错误类型生效。它定义在 packages/effect/src/Cause.ts#L1197-L1223是YieldableError的子类拥有专属类型标识NoSuchElementErrorTypeId值为~effect/Cause/NoSuchElementError携带_tag: NoSuchElementError可判别字段构造函数new Cause.NoSuchElementError(message?: string)支持可选错误消息便于调试定位例如Element not found通过Cause.isNoSuchElementError(value)类型守卫进行运行时判定。在 v4 中NoSuchElementError通常由两条入口产生恰与catchNoSuchElement形成闭合的转换回路Effect.fromOptionEffect.ts#L1846-L1860接收Option当传入Option.none时以NoSuchElementError失败Effect.fromNullishOrEffect.ts#L1922接收可能为 null/undefined 的值nullish 时以NoSuchElementError失败。实战用法三个可直接运行的示例catchNoSuchElement的使用形态是管道风格.pipe(...)作用于任意可能产生NoSuchElementError的 Effect。以下是文档与测试中的真实用例。示例一fromNullishOr 后的可选恢复文档示例Effect.ts#L3427-L3439import { Effect, Option } from effect const some Effect.fromNullishOr(1).pipe(Effect.catchNoSuchElement) const none Effect.fromNullishOr(null).pipe(Effect.catchNoSuchElement) Effect.runSync(some) // Option.some(1) Effect.runSync(none) // Option.none()fromNullishOr(null)原本会以NoSuchElementError失败经catchNoSuchElement后变为成功值Option.none()错误通道被清空。示例二head 取首个元素失败时返回 NoneEffect.headEffect.ts#L817-L819在集合为空时会以NoSuchElementError失败配合catchNoSuchElement可将空集合这一业务含义安全地落到Option上Effect.ts#L804-L812import { Effect, Option } from effect const first Effect.head(Effect.succeed([1, 2, 3])) .pipe(Effect.catchNoSuchElement) const empty Effect.head(Effect.succeed([] as Arraynumber)) .pipe(Effect.catchNoSuchElement) await Effect.runPromise(first) // Option.some(1) await Effect.runPromise(empty) // Option.none()示例三其他错误保持不变这是最重要的边界行为——catchNoSuchElement只吞掉NoSuchElementError其余失败原样透传Effect.test.ts#L2531-L2536import { Effect, Option, Exit } from effect class ErrorA { readonly _tag ErrorA } const error new ErrorA() const result Effect.fail(error).pipe(Effect.catchNoSuchElement, Effect.exit) // Exit.fail(error)ErrorA 不会被转换在 Effect.gen 生成器中的使用运行时测试展示了在生成器中的惯用写法Effect.test.ts#L2522-L2529import { Effect, Option } from effect Effect.gen(function*() { const some yield* Effect.fromNullishOr(value).pipe(Effect.catchNoSuchElement) // some Option.some(value) const none yield* Effect.fromNullishOr(null as string | null) .pipe(Effect.catchNoSuchElement) // none Option.none() })由于Exclude在类型层面移除了NoSuchElementError生成器中yield*解包出来的值类型就是OptionAEffect.gen无需再处理该错误分支代码更贴近顺序编程直觉。与 option 原语的边界精确 vs 全量转换catchNoSuchElement与既有 APIEffect.optionEffect.ts#L2297经常被放在一起比较但两者语义差异巨大对比维度Effect.catchNoSuchElementEffect.option转换范围仅NoSuchElementError失败所有失败转换结果Option.some(a)/Option.none()Option.some(a)/Option.none()转换后错误通道ExcludeE, NoSuchElementErrornever适用场景只想把缺失当作业务分支其余错误继续传播完全吸收错误进入纯成功世界实践中推荐按此决策如果元素缺失是程序预期的分支如数据库按主键查询无结果、集合取头元素为空、配置项未设置优先用catchNoSuchElement保住错误通道的类型信息只有当调用方确实不在意具体失败原因时才用option一揽子吸收。从 v3 optionFromOptional 迁移由于catchNoSuchElement是 v3optionFromOptional的重命名移植迁移文档 migration/v3-to-v4.md#L9763 给出了相关指引同时迁移注释清单 migration/annotations/effect__Effect.yaml#L331 中仍保留着effect/Effect#optionFromOptional的条目。迁移时需要注意旧名optionFromOptional在新版中不再作为 Effect 层的 API 导出新的等效入口就是Effect.catchNoSuchElement命名更贴近其捕获特定失败的语义与catchTag、catchIf、catchAll等catch*家族保持一致语义等价两者都是成功值 →Option.someNoSuchElementError→Option.none其他错误透传需要同步调整导入与调用方式由接收 Option 输入的构造风格改为作用于任意 Effect 的管道风格。类型层面保证typetest 的静态验证除了运行时测试仓库还为catchNoSuchElement编写了类型测试 packages/effect/typetest/Effect.tst.ts#L584-L594describe(Effect.catchNoSuchElement, () { it(removes NoSuchElementError from the error channel, () { const result pipe(noSuchOrOther, Effect.catchNoSuchElement) expect(result).type.toBeEffect.EffectOption.Optionstring, OtherError() }) it(yields never when NoSuchElementError is the only error, () { const result pipe(onlyNoSuch, Effect.catchNoSuchElement) expect(result).type.toBeEffect.EffectOption.Optionnumber() }) })这两条断言精确锁定了类型契约当错误通道混合NoSuchElementError | OtherError时转换后仅剩OtherError当错误通道只有NoSuchElementError时转换后错误通道为never类型系统强制保证后续代码无需再处理该错误。适用前提与限制最后总结catchNoSuchElement的边界避免误用只处理类型化失败NoSuchElementError属于YieldableError类型化错误如果 Effect 以Effect.die产生缺陷defect或遭遇中断interruptionmatchEffect的失败分支不会以普通错误路径进入catchNoSuchElement不会捕获它们严格匹配单一错误类型它不做谓词判断仅通过isNoSuchElementError守卫精确匹配任何其他错误包括NoSuchElementError之外的业务错误都会原样传播version 前提该 API 标记since 4.0.0仅存在于 effect 4.x 版本线v3 项目请继续使用optionFromOptional或按 迁移文档 升级。综上Effect.catchNoSuchElement是 Effect 4.0 错误处理工具箱中一个小而精确的成员它以一行管道调用把查找不到从错误域安全转移到数据域Option同时不牺牲错误通道的类型精度是处理可选查询、集合取首元素、配置缺省等场景的推荐原语。【免费下载链接】t3code项目地址: https://gitcode.com/GitHub_Trending/t3/t3code创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →