mcpField
N
neverthrow-wrap-exceptions

neverthrow-wrap-exceptions

github.com/code-sherpas开发045 次安装1 天前更新
代码仓库

关于 neverthrow-wrap-exceptions

neverthrow-wrap-exceptions 是面向编码的技能,用于将可恢复的同步和异步异常转换为带类型的 neverthrow 结果,并指导开发者选择包装方法、显式映射错误。

主要功能

  1. 01按失败类型选择包装方法
  2. 02将错误映射为明确类型
  3. 03组合现有 Result 值
  4. 04替换仅用于转换的 catch 链
  5. 05检查异常处理变更

适用场景

  1. 01包装可能抛出异常的同步解析器
  2. 02将拒绝的 Promise 转换为领域错误
  3. 03重构基于 catch 的临时转换
  4. 04审查代码中的错误处理

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/code-sherpas/agent-skills --skill neverthrow-wrap-exceptions

安装后在 Claude Code 中输入/neverthrow-wrap-exceptions确认已加载。

详细介绍

neverthrow 异常封装

目标

使用 neverthrow 辅助函数捕获可恢复的异常,而不是随意使用 try/catch。

此技能仅适用于异常捕获。如果任务还会更改公开的返回签名,请同时使用 neverthrow-return-types。

检测异常来源

  1. 找出失败当前从何处进入代码。

    • 查找手写的 try/catch、仅用于转换的 .catch(...) 封装、已知会抛出异常的 API 的直接调用,以及可能拒绝的返回 Promise 的函数。
    • 检查第三方库、解析器、数据库客户端、网络客户端、文件系统辅助函数、架构验证器和序列化代码。
  2. 在选择封装函数前,区分失败形态。

    • 如果操作可能在返回值之前抛出异常,则使用同步路径。
    • 如果操作返回 Promise,但在该 Promise 创建之前仍可能抛出异常,则使用 Promise 函数路径。
    • 如果手头已经有 PromiseLike 值,则使用 Promise 实例路径。
  3. 不要封装已经返回 Result 或 ResultAsync 的 API。

    • 直接使用 map、mapErr、andThen、asyncAndThen 或 orElse 组合。

选择封装函数

  1. 对于会抛出异常的同步函数,使用 Result.fromThrowable 或 fromThrowable。

    • 始终传入错误映射函数,以便 Err 一侧具有明确的类型。
  2. 对于可能在返回前抛出异常或在异步执行期间失败的返回 Promise 的函数,使用 ResultAsync.fromThrowable。

    • 如果函数调用本身可能抛出异常,优先使用此方法,而不是 ResultAsync.fromPromise(fn(...), ...)。
  3. 如果手头已经有 PromiseLike 值,则使用 ResultAsync.fromPromise 或 fromPromise。

    • 立即将拒绝值映射为具体的错误类型。
  4. 当同一种错误形态反复出现时,复用范围明确的映射函数。

    • 优先使用稳定的领域错误,而不是 unknown、any 和泛化字符串。

默认避免 try/catch

  1. 如果 neverthrow 辅助函数适用,不要新增手写的 try/catch 块。

    • 如有需要,将存在风险的操作提取为函数,再封装该函数。
  2. 只有当周围的结构确实需要时才保留 try/catch。

    • 例如需要 finally 的清理流程、必须拦截并转换异常的框架边界,或者无法仅通过封装辅助函数清晰表达的语言结构。
  3. 如果必须保留 try/catch,应将其置于范围最窄的边界。

    • 立即将捕获的值转换为 Err 或所需的框架原生响应。
    • 不要让捕获的值以未类型化的 unknown 在代码库中流转。

实现规则

  1. 在可能抛出异常或拒绝的操作源头附近封装一次。

    • 避免对同一操作进行嵌套封装。
  2. 明确进行错误映射。

    • 如果符合本地代码风格,优先使用能保留有用上下文的映射函数,例如操作名称、输入标识符或上游状态码。
  3. 当 neverthrow 提供了更清晰的封装方式时,替换仅用于转换的 .catch(...) 链。

    • 不要使用 Promise.resolve、Promise.reject 或自定义封装对象手动模拟 ResultAsync。

示例模式

const parseConfig = Result.fromThrowable(
  JSON.parse,
  (error) => ({ type: 'ConfigParseError', cause: error }),
)

const fetchUser = ResultAsync.fromThrowable(
  apiClient.getUser,
  (error) => ({ type: 'UserFetchError', cause: error }),
)

function readBody(): ResultAsync<RequestBody, BodyReadError> {
  return ResultAsync.fromPromise(request.json(), toBodyReadError)
}

完成前验证

  1. 确认新增或修改的失败捕获在适用时使用了 neverthrow 辅助函数。
  2. 确认每种封装函数的选择都符合实际失败形态:同步抛出异常、返回 Promise 的函数,或现有 Promise。
  3. 确认所有错误映射函数都生成了明确的错误类型。
  4. 确认任何保留的 try/catch 块都有实际约束作为理由,而非仅仅沿袭习惯。
  5. 在安全且任务范围允许的情况下,运行当前技术栈的常规本地验证,例如测试、代码检查或类型检查。

报告结果

完成任务时:

  • 说明包装了哪些会抛出异常或拒绝的操作。
  • 说明使用了哪个 neverthrow 辅助函数,以及原因。
  • 说明还保留了哪些 try/catch 代码块,以及它们为何不可避免。
  • 说明如何将捕获或拒绝的值映射为显式错误类型。

评论

支持 Markdown