关于 neverthrow-return-types
neverthrow-return-types 是一项面向 TypeScript 开发任务的技能,指导将兼容的函数和方法建模为 neverthrow 的 Result 或 ResultAsync。它先识别框架等边界的返回契约,并要求在边界内部保留 neverthrow 错误处理。
主要功能
- 01识别函数与方法的返回契约
- 02同步逻辑使用 Result
- 03异步逻辑使用 ResultAsync
- 04在不兼容边界内封装 neverthrow 结果
- 05检查错误类型、导入和验证
适用场景
- 01统一服务、仓库和领域 API 的返回类型
- 02重构对象方法或类方法的错误返回
- 03在框架回调边界适配内部 Result
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ code-sherpas/ agent-skills --skill neverthrow-return-types安装后在 Claude Code 中输入/neverthrow-return-types确认已加载。
详细介绍
Neverthrow 返回类型
目标
使用 neverthrow 返回类型为所有兼容的函数和方法建模。
此技能仅规定返回签名。如果任务还需要更改对抛出异常或被拒绝的 Promise 的捕获方式,请同时使用 neverthrow-wrap-exceptions。
对以下项目应用此规则:
- 独立函数
- 导出的模块函数
- 类方法
- 对象字面量方法
- 工厂返回的方法
- 服务、存储库和领域 API
不要因为代码嵌套就将其视为例外。类或对象中的方法与顶层函数遵循相同规则。
唯一允许的例外是周边技术、库或框架强制要求的不兼容边界。
首先检测兼容性
-
编辑前,确定函数或方法的实际契约。
- 检查已实现的接口、被重写的成员、框架回调类型、装饰器、生命周期钩子、路由处理器签名、组件签名和公共 SDK 契约。
- 如果契约已要求使用
Result或ResultAsync,则保留该类型。 - 如果契约要求其他返回形式,则该边界不兼容。
-
除非本地技术明确支持返回
neverthrow类型,否则将以下情况视为常见的不兼容边界:- 必须返回元素或节点的 UI 渲染函数。
- 必须返回
Response、框架回复对象、void或这些值的Promise的框架路由处理器、中间件、加载器、操作函数、控制器或解析器。 - 具有固定运行时签名的事件监听器、测试回调、构造函数、getter、setter 和其他 API。
- 返回类型无法扩宽为
Result或ResultAsync的接口实现或被重写方法。
-
存在不兼容时,在边界内部使用
neverthrow。- 将业务逻辑移入返回
Result或ResultAsync的内部辅助函数或方法。 - 仅在最外层边界,将最终的
Ok或Err转换为框架原生返回值。 - 不要仅仅因为边界本身无法返回
neverthrow,就退回到临时拼凑的失败形式,例如null、哨兵值或框架专用捷径。
- 将业务逻辑移入返回
-
如果目标项目尚未依赖
neverthrow,只有在任务允许更改依赖项时才添加该依赖。- 如果不允许更改依赖项,请说明目前无法完全应用此策略。
选择返回类型
- 对同步工作使用
Result<T, E>。 - 对异步工作使用
ResultAsync<T, E>。 - 优先为
E使用明确的领域错误类型。- 使用判别联合、带标签的对象或符合本地风格的稳定错误类。
- 除非代码库已将其作为标准,否则避免使用
unknown、any和含糊的字符串错误。
- 使用
ok(...)、err(...)、okAsync(...)和errAsync(...)显式构造成功和失败值。
实现规则
-
如果函数或方法的公共契约应为
ResultAsync<T, E>,不要将其标记为async。- 直接返回
ResultAsync,以便调用方使用.map、.mapErr、.andThen和.orElse进行组合。 - 除非框架边界明确要求原生
Promise,否则避免使用Promise<Result<T, E>>。
- 直接返回
-
修改模块时,更新该作用域中所有被编辑的兼容函数和方法。
- 如果它们属于同一项请求的更改,不要只转换顶层函数,却让相邻的兼容类方法或对象方法继续使用非
neverthrow签名。
- 如果它们属于同一项请求的更改,不要只转换顶层函数,却让相邻的兼容类方法或对象方法继续使用非
边界模式
当外部 API 无法返回 neverthrow 时,使用以下模式:
function createUser(
input: CreateUserInput,
): ResultAsync<User, CreateUserError> {
return validateInput(input).asyncAndThen(insertUser)
}
export async function post(request: Request): Promise<Response> {
const result = await createUser(await request.json())
return result.match(
(user) => Response.json(user, { status: 201 }),
(error) => toErrorResponse(error),
)
}
完成前验证
- 验证每个已编辑且兼容的函数或方法现在都返回
Result或ResultAsync。 - 验证不兼容的边界会适配内部的
neverthrow结果,而不是绕过它们。 - 验证导入来自
neverthrow,且与实际用法相符。 - 验证错误类型是显式的,且对调用方足够稳定。
- 在安全且属于任务范围的情况下,运行技术栈的常规本地验证,例如测试、lint 或类型检查。
报告结果
完成任务时:
- 说明哪些函数或方法现在返回
Result或ResultAsync。 - 说明哪些边界仍未使用
neverthrow,以及它们不兼容的原因。 - 说明
Err值如何进行类型声明和映射。
评论
支持 Markdown