【发布时间】:2021-05-10 13:44:32
【问题描述】:
我正在努力将获取的数据“按摩”成我想要的形状,使用fp-ts 进行功能转换,使用io-ts 进行数据验证。
我在寻找什么
我希望 getSchools() 返回描述问题所在的 Error 或经过验证的 Schools 数组。我的代码有些工作,但问题是,如果获取的学校数组中的一所学校未能通过验证,那么一切都会失败。我想只过滤掉那些失败的,然后返回其余的。
我目前的代码
/**
* API route for all Schools
*/
export default async (_: NextApiRequest, res: NextApiResponse<unknown>) => {
return new Promise(
pipe(
getSchools(),
fold(
(e) => of(res.status(400).end(e.message)),
(v) => of(res.status(200).json(v))
)
)
);
};
/**
* Handler for fetching Schools
*/
export function getSchools(): TaskEither<Error, Array<School>> {
return pipe(
fetch(schoolQuery(schoolQueryBody)),
chain(mapToschools),
chain(decode(t.array(School)))
);
}
function mapToschools(
inputs: Array<any>
): TaskEither<Error, Array<School>> {
try {
return right(inputs.map(mapToschool));
} catch (e) {
return left(new Error("Could not map input to school"));
}
}
export function mapToschool(input: any): School // Can throw Error
export const schoolQueryBody = `...`;
function fetch(query: string): TaskEither<Error, unknown>
export function decodeError(e: t.Errors): Error {
const missingKeys = e.map((e) => e.context.map(({ key }) => key).join("."));
return new Error(`Missing keys: ${missingKeys}`);
}
export const decode = <I, A>(Type: t.Decoder<I, A>) => (
res: I
): TaskEither<Error, A> => {
return pipe(fromEither(Type.decode(res)), mapLeft(decodeError));
};
【问题讨论】:
-
通常这是使用称为
Validation的特殊类型完成的。 AFAIK,FP-TS 不包含它,但似乎有一个替代的Applicative实例用于Either,它允许收集所有错误语义。 More. -
验证是使用
io-ts完成的,并且有效,我的问题更多是关于映射和结果数组,可以是左或右,也可以是正好的数组,或类似的东西。 -
先解码任意数组然后再解码数组项(School)怎么样?
-
也许可以这样做,但应该可以以某种方式映射结果?然后过滤结果还是什么?
标签: javascript typescript functional-programming fp-ts