【发布时间】:2021-03-11 00:20:19
【问题描述】:
假设我有以下类型:
type ValidatedInput = Readonly<{
id: string
}>
type GetStructures = (id: string) => TaskEither<ServiceError, ReadonlyArray<SomeStructure>>
type GetOtherStructures = (ids: ReadonlyArray<string>) => TaskEither<ServiceError, ReadonlyArray<SomeOtherStructure>>
type LookupThings = (initialInput: ReadonlyArray<SomeStructure>, additionalInput: ReadonlyArray<SomeOtherStructure>) => TaskEither<ServiceError, ReadonlyArray<Option<ResponseType>>>
export type Deps = Readonly<{
getStructures: GetStructures
getOtherStructures: GetOtherStructures
lookupThings: LookupThings
}>
export type Ctx<T> = ReaderTaskEither<Deps, Error, T>
还有以下错误处理助手:
type Code = 'INVALID_ENTITY' | 'INVALID_API_KEY'
export const fromCode = (code: Code): Error => ({
tag: 'validation',
code
})
然后我像这样创建一个函数:
const constructFullData = (input: ValidatedInput): Ctx<ReadonlyArray<Option<ResponseType>>> => (
(deps: Deps): TE.TaskEither<Error, ReadonlyArray<Option<ResponseType>>> => (
pipe(
deps.getStructures(input.id),
TE.map((structs) => pipe(
deps.getOtherStructures([structs[0].higherOrderId]),
TE.chain(otherStructs => pipe(
deps.lookupThings(structs, otherStructs),
TE.chain(results => {
if (results.filter(isNone).length !== results.length) {
return TE.left(fromCode('INVALID_ENTITY')) // I'm not sure what a better way to filter this is. Ideally the return type of this function wouldn't have an Option in it
} else {
return TE.right(results)
}
})
))
)),
TE.flatten
)
)
)
这一切都编译得很好,但我真正想要的是返回一个没有过滤掉的数组,如果没有则引发相应的错误!
天真的做法是将Right path的返回改为:
return TE.right(results.map(u => u.value))
但这并不能编译,抛出如下错误:
Property 'value' does not exist on type 'None'.
64 return TE.right(usagesWithDrones.map(u => u.value))
如何应用这种过滤?
【问题讨论】:
-
如果我错了,请纠正我,但是“我真正想要的是返回一个没有过滤掉的数组,如果没有则引发适当的错误”意味着你想要返回原始数组(如果它们都是 Some),或者如果只有一个 None,则返回错误。为此,
fp-ts/Array有sequence:假设 x 是Option<number>[],那么Array.sequence(option)(x)将产生Some<number[]>如果它们都是 Some 或None如果即使单个是 None 。
标签: typescript functional-programming fp-ts