← 中文资源

简体中文版本

用 Result 类型替代抛异常

以 ok 标记的 Result 联合类型配合 map、mapErr、andThen 与 unwrapOr,把错误路径显式化并交给编译器检查。

阅读英文原文

功能说明

异常在类型系统中不可见,调用方容易忘记处理失败路径,重构时也可能悄悄丢掉 catch。该示例定义 Result<T, E> 联合类型,用 ok 与 err 构造成功或失败,再提供 map、mapErr、andThen 和 unwrapOr 四个组合子。所有错误都作为值返回,调用链无需 try/catch,类型签名会提示必须处理的分支。

关键代码

Result 是以 ok 布尔字段区分的可辨识联合,成功携带 value,失败携带 error。ok 返回 Result<T, never>,err 返回 Result<never, E>,便于赋给任意期望类型。map 只转换成功值,失败原样返回;mapErr 只转换错误;andThen 用于串联可能失败的步骤,遇到失败立即短路;unwrapOr 在失败时返回调用方提供的兜底值。组合子内部不抛异常。

export function andThen<T, U, E>(
  result: Result<T, E>,
  fn: (value: T) => Result<U, E>,
): Result<U, E> {
  return result.ok ? fn(result.value) : result;
}

使用注意

组合子要求同一链条上的错误类型一致,混合多种错误时需要先统一映射,否则类型检查不通过。示例为同步实现,没有异步组合子,也没有 all、any 之类的集合辅助函数。Result 会包裹每一层返回值,与现有抛异常代码或第三方库对接时需要适配层。unwrapOr 会吞掉具体错误原因,只适合确实可忽略失败的场景。

验证方式

运行随附测试:对 ok(2) 执行乘以 3 的 map 应得到 ok(6),对 err 执行同一映射应保留错误;mapErr 只改变错误长度;把字符串解析与正数校验组合进 andThen,确认失败会短路且错误信息正确;unwrapOr 对 ok 与 err 分别返回原值与兜底值。