如何使用 sequenceT 和 ReaderTaskEither 发出两个具有不同错误类型的并行请求?
How to make two parallel requests with different error types using sequenceT and ReaderTaskEither?
我想使用 sequenceT
函数发出两个并行请求并处理结果,但它显示了一个我无法自行解决的错误
import * as RTE from 'fp-ts/ReaderTaskEither'
import * as Ap from 'fp-ts/Apply'
Ap.sequenceT(RTE.ApplyPar)(
getUserById('1'),
getSpecialistById('2')
) // <- This method shows error
错误
Type 'SpecialistNotFoundError' is not assignable to type 'UserNotFoundError'.
Types of property 'code' are incompatible.
Type '"SPECIALIST_NOT_FOUND"' is not assignable to type '"USER_NOT_FOUND"'
可能有助于理解问题的代码
function getSpecialistById (specialistId: string): RTE.ReaderTaskEither<PrismaClient, SpecialistNotFoundError, Specialist> {
return (prisma: PrismaClient) => {
return TE.tryCatch(
() => prisma.specialist.findUnique({ where: { id: specialistId }, rejectOnNotFound: true }),
() => new SpecialistNotFoundError()
)
}
}
function getUserById (userId: string): RTE.ReaderTaskEither<PrismaClient, UserNotFoundError, User> {
return (prisma: PrismaClient) => {
return TE.tryCatch(
() => prisma.user.findUnique({ where: { id: userId }, rejectOnNotFound: true }),
() => new UserNotFoundError()
)
}
}
class UserNotFoundError extends Error {
readonly code = 'USER_NOT_FOUND'
constructor () {
super('User not found')
}
}
class SpecialistNotFoundError extends Error {
readonly code = 'SPECIALIST_NOT_FOUND'
constructor () {
super('Specialist not found')
}
}
我认为与其使用 sequenceT
(因为我认为它无法正确处理您要执行的操作的类型),不如使用 Do
符号,如下所示:
const result = pipe(
RTE.Do,
RTE.apS("user", getUserById("1")),
RTE.apSW("spec", getSpecialistById("2")),
RTE.map(({ user, spec }) => {
return `${user.id}:${spec.id}`;
})
);
在这种情况下,result
将是 RTE.ReadTaskEither<PrismaClient, UserNotFoundError | SpecialistNotFoundError, string>
,因为我在 map
中返回了 string
。
这里是the docs on Do
notation。请注意底部显示如何并行执行操作的地方
我想使用 sequenceT
函数发出两个并行请求并处理结果,但它显示了一个我无法自行解决的错误
import * as RTE from 'fp-ts/ReaderTaskEither'
import * as Ap from 'fp-ts/Apply'
Ap.sequenceT(RTE.ApplyPar)(
getUserById('1'),
getSpecialistById('2')
) // <- This method shows error
错误
Type 'SpecialistNotFoundError' is not assignable to type 'UserNotFoundError'.
Types of property 'code' are incompatible.
Type '"SPECIALIST_NOT_FOUND"' is not assignable to type '"USER_NOT_FOUND"'
可能有助于理解问题的代码
function getSpecialistById (specialistId: string): RTE.ReaderTaskEither<PrismaClient, SpecialistNotFoundError, Specialist> {
return (prisma: PrismaClient) => {
return TE.tryCatch(
() => prisma.specialist.findUnique({ where: { id: specialistId }, rejectOnNotFound: true }),
() => new SpecialistNotFoundError()
)
}
}
function getUserById (userId: string): RTE.ReaderTaskEither<PrismaClient, UserNotFoundError, User> {
return (prisma: PrismaClient) => {
return TE.tryCatch(
() => prisma.user.findUnique({ where: { id: userId }, rejectOnNotFound: true }),
() => new UserNotFoundError()
)
}
}
class UserNotFoundError extends Error {
readonly code = 'USER_NOT_FOUND'
constructor () {
super('User not found')
}
}
class SpecialistNotFoundError extends Error {
readonly code = 'SPECIALIST_NOT_FOUND'
constructor () {
super('Specialist not found')
}
}
我认为与其使用 sequenceT
(因为我认为它无法正确处理您要执行的操作的类型),不如使用 Do
符号,如下所示:
const result = pipe(
RTE.Do,
RTE.apS("user", getUserById("1")),
RTE.apSW("spec", getSpecialistById("2")),
RTE.map(({ user, spec }) => {
return `${user.id}:${spec.id}`;
})
);
在这种情况下,result
将是 RTE.ReadTaskEither<PrismaClient, UserNotFoundError | SpecialistNotFoundError, string>
,因为我在 map
中返回了 string
。
这里是the docs on Do
notation。请注意底部显示如何并行执行操作的地方