
本文详解如何使用 orElse 正确处理 TaskEither 中异步失败路径,实现左右两侧统一为 TaskEither 类型,避免嵌套结构,并支持后续链式调用。
本文详解如何使用 `orelse` 正确处理 `taskeither` 中异步失败路径,实现左右两侧统一为 `taskeither
在函数式编程实践中,TaskEither
你遇到的问题非常典型:
const result = pipe( input, TE.right, TE.chain(requestChatMessage), TE.map(success), // ✅ success: string → TE.TaskEither<Error, string> TE.mapLeft(fail) // ❌ fail: Error → TE.TaskEither<Error, Error> ); // 类型变为:TE.TaskEither<TE.TaskEither<Error, Error>, string> // 即 Left 侧未被“展开”,形成嵌套,无法继续链式调用
关键误区在于:mapLeft 仅对 Left 值做同步转换,它不会执行异步逻辑,也不会扁平化返回的 TaskEither。要让 Left 分支也执行异步操作并融入同一层级的 TaskEither 结构,必须使用 orElse —— 它是 TaskEither 的 chainLeft,语义为:“当当前值为 Left(e) 时,用 e 调用提供的函数,该函数应返回一个新的 TaskEither
✅ 正确做法如下:
import * as TE from 'fp-ts/TaskEither';
import { pipe } from 'fp-ts/function';
// 假设类型定义
type Input = string;
type SuccessResult = string;
type FailureResult = Error;
// 异步成功处理器:string → Promise<string>
const onRequestSuccess = (result: string): Promise<string> =>
Promise.resolve(`Processed: ${result}`);
// 异步失败处理器:Error → Promise<Error>
const onRequestFail = (error: Error): Promise<Error> =>
Promise.resolve(new Error(`Handled: ${error.message}`));
// 将异步函数安全包裹为 TaskEither
const safeOnRequestSuccess = (result: string) =>
TE.tryCatch(() => onRequestSuccess(result), () => new Error('onRequestSuccess failed'));
const safeOnRequestFail = (error: Error) =>
TE.tryCatch(() => onRequestFail(error), () => new Error('onRequestFail failed'));
// 核心流程:使用 orElse 处理 Left 分支
const finalFlow = (input: Input) =>
pipe(
input,
TE.right, // 初始化为 Right(input)
TE.chain(requestChatMessage), // 假设 requestChatMessage: string → TE.TaskEither<Error, string>
TE.chain(safeOnRequestSuccess), // 成功后继续异步处理(Right 分支)
TE.orElse(safeOnRequestFail) // ⚠️ 关键:当上一步为 Left(err) 时,用 err 调用 safeOnRequestFail
);
// 最终类型为:() => Promise<Either<Error, string>>
// 可无缝接入后续 chain/fold:
const finalResult = pipe(
finalFlow("hello"),
TE.chain((data) => TE.right(`Final: ${data}`)), // 继续处理成功数据
TE.fold(
(e) => console.error('Failed:', e.message),
(a) => console.log('Success:', a)
)
);? 重要注意事项:
- orElse 的参数函数接收 Left 值(即错误),必须返回 TaskEither
,而非普通 Promise 或 Either ;否则类型不匹配。 - 若需统一左右两侧的错误类型(如都转为 AppError),可在 safeOnRequestFail 内完成转换,orElse 会自然继承其 Left 类型。
- 不要尝试用 flattenW 处理 Left —— flattenW 仅作用于 TaskEither
, A> 这类右嵌套结构,对左嵌套无效。 - orElse 是 chainLeft 的别名,语义清晰:它“重写”失败路径,使其产出与成功路径同构的 TaskEither。
✅ 总结:当你需要在 TaskEither 流程中对失败分支执行异步逻辑并保持类型扁平,orElse 是唯一正确且符合函数式语义的工具。它确保整个管道始终处于 TaskEither










