FT-TS:如何扁平化TaskEither的左侧?
解决TaskEither左侧嵌套扁平化问题
场景与问题
已知:
OnRequestSuccess是执行操作并返回字符串的异步函数OnRequestFailure是执行操作并返回Error的异步函数
在使用fp-ts的TaskEither构建异步流程时,尝试通过map处理成功分支、mapLeft处理失败分支后,再用flattenW只能解决右侧的嵌套问题,左侧仍会出现TaskEither<Error | TE.TaskEither<Error, Error>, string>的嵌套结构,无法得到能直接传入后续异步函数的统一类型。
原问题代码:
const success = (result: string) => TE.tryCatch(() => onRequestSuccess(result), E.toError); const fail = (result: Error) => TE.tryCatch(() => onRequestFail(result), E.toError); // 存在嵌套问题的代码 const result = pipe( input, TE.right, TE.chain(requestChatMessage), TE.map(success), TE.mapLeft(fail), TE.flattenW );
解决方案
核心是用orElseW替代mapLeft处理错误分支,同时用chain替代map处理成功分支,让异步操作直接融入TaskEither流程,避免嵌套。
调整后的完整代码
import * as TE from 'fp-ts/TaskEither'; import * as E from 'fp-ts/Either'; import { pipe } from 'fp-ts/function'; // 示例异步成功处理函数 const onRequestSuccess = (result: string): Promise<string> => { return Promise.resolve(`处理成功:${result}`); }; // 示例异步失败处理函数 const onRequestFail = (err: Error): Promise<Error> => { return Promise.reject(new Error(`处理失败:${err.message}`)); }; // 示例请求函数 const requestChatMessage = (input: unknown): TE.TaskEither<Error, string> => { return TE.tryCatch(() => Promise.resolve('聊天请求响应'), E.toError); }; // 修正后的流程 const result = pipe( input, TE.right, TE.chain(requestChatMessage), // 成功分支用chain扁平化异步处理的TaskEither TE.chain(res => TE.tryCatch(() => onRequestSuccess(res), E.toError)), // 错误分支用orElseW整合异步处理,避免左侧嵌套 TE.orElseW(err => TE.tryCatch(() => onRequestFail(err), E.toError) // 可选:如果希望失败处理的结果进入成功分支,添加此行;否则保留错误分支 // .mapLeft(E.right) ) );
转为可传入后续函数的Task
如果需要将最终结果转为Task(即Promise<Either<Error, string | Error>>),方便传入后续异步函数,可以用foldW处理:
// 转为统一的Task类型 const finalTask = pipe( result, TE.foldW( err => TE.of(err) as TE.TaskEither<never, Error>, res => TE.of(res) as TE.TaskEither<never, string> ), TE.toTask ); // 后续异步调用示例 const finalCall = (value: string | Error): Promise<void> => { console.log('最终处理值:', value); return Promise.resolve(); }; // 执行流程并传入后续函数 finalTask().then(finalCall);
关键说明
TE.chain替代TE.map:因为成功分支的异步处理返回TaskEither,chain会自动扁平化右侧嵌套,无需额外flatten。TE.orElseW替代TE.mapLeft:orElseW允许接收错误并返回新的TaskEither,直接将错误分支的异步操作纳入主流程,彻底避免左侧嵌套。
内容的提问来源于stack exchange,提问作者Morphex
相关产品推荐
相关产品推荐

