fp-ts/typescript 避免嵌套管道
fp-ts/typescript avoid nested pipes
在打字稿中使用 fp-ts 时如何避免嵌套管道?做记号?这是我想避免的嵌套管道示例
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))
)
);
});
}
)
);
一种方法是尽可能延迟 fold
以避免不必要的嵌套。
代数效应可以在不知道值是否存在或操作失败的情况下构成。
例如,如果没有找到用户,用 chain
转换的 TaskEither
将保留第一个错误。否则,它包含 fetchUser
错误或成功案例中的 User
数据。
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
。
在打字稿中使用 fp-ts 时如何避免嵌套管道?做记号?这是我想避免的嵌套管道示例
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))
)
);
});
}
)
);
一种方法是尽可能延迟 fold
以避免不必要的嵌套。
代数效应可以在不知道值是否存在或操作失败的情况下构成。
例如,如果没有找到用户,用 chain
转换的 TaskEither
将保留第一个错误。否则,它包含 fetchUser
错误或成功案例中的 User
数据。
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
。