fp-ts / typescript避免嵌套管道

时间:2020-06-12 23:49:07

标签: typescript fp-ts

在打字稿中使用fp-ts时如何避免嵌套管道?记谱法吗?这是我要避免的嵌套管道的示例

message.channel.send('Hello').catch(e => {
  // do error handling here
  console.log(e)
})

1 个答案:

答案 0 :(得分:2)

一种方法是尽可能延迟fold以避免不必要的嵌套。

无需知道数值是否存在或运算失败就可以构成代数效应。

例如,如果未找到用户,则用chain转换的TaskEither将保留第一个错误。否则,它包含fetchUser错误或成功情况下的User数据。

Working example

import { pipeable as P, option as O, taskEither as TE, nonEmptyArray as NA } from "fp-ts";

type User = { name: string };

// global state (side effect)
let user: string | undefined = undefined;
const setUser = (usr: string) => (user = usr);

// given input
const userId: O.Option<string> = O.some("Arun");

const fetchUser: (uid: string) => TE.TaskEither<NA.NonEmptyArray<string>, User> = uid =>
  TE.taskEither.of({ name: "Arun" });
  // An error case would be: TE.left(NA.of("Unable to fetch user"))  

const res = P.pipe(
  userId,
  TE.fromOption(() => NA.of("No user found")),
  TE.chain(fetchUser),
  TE.map(user => JSON.stringify(user, null, 2)),
  TE.fold( // we fold at the very end before applying the effect
    err => TE.taskEither.fromIO(() => { setUser(err[0]); }),
    user => TE.taskEither.fromIO(() => { setUser(JSON.stringify(user, null, 2)); })
  ),
  TE.chain(() => TE.taskEither.fromIO(() => { console.log(user); }))
);

// run the effect
res();

PS:我在这里假设您的fetchUser是一个异步操作,它创建了TaskEither。您可以根据需要将其切换回Either