简体   繁体   English

fp-ts/typescript 避免嵌套管道

[英]fp-ts/typescript avoid nested pipes

How can I avoid nested pipes when using fp-ts in typescript?在 typescript 中使用 fp-ts 时如何避免嵌套管道? Do notation?做记号? Here's an example of nested pipe I want to avoid这是我想避免的嵌套 pipe 的示例

  pipe(
  userId,
  O.fold(
    () => setUser('No user found'),
    (uId: string) => {
      fetchUser(uId).then((response: Either<NonEmptyArray<string>, User>) => {
        pipe(
          response,
          E.fold(
            () => setUser('Unable to fetch user'),
            (user: User) => setUser(JSON.stringify(user, null, 2))
          )
        );
      });
    }
  )
);

One way is to delay fold as long as possible to avoid unnecessary nesting.一种方法是尽可能地延迟fold以避免不必要的嵌套。

Algebraic effects can be composed without needing to know, if a value is existent or an operation has failed.无需知道值是否存在或操作是否失败,就可以组合代数效应。

For example, a TaskEither transformed withchain will keep the first error, if no user has been found.例如,如果未找到用户,则使用chain转换的TaskEither将保留第一个错误。 Otherwise, it contains either the fetchUser error or the User data in success case.否则,它包含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: I assumed here, your fetchUser is an async operation, which creates TaskEither . PS:我在这里假设,您的fetchUser是一个异步操作,它创建了TaskEither You can switch it back to Either , if needed.如果需要,您可以将其切换回Either

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM