カスタムエラーデータをSemigroupでサマリあげるワークアラウンドの紹介
こんにちわ。nap5です。
カスタムエラーデータをSemigroupでサマリあげるワークアラウンドの紹介をしたいと思います。
collectError関数はユーザー定義でnarrowingしていますが、もう少しいい書き方ありそうです。ちょっとぱっと思いつきませんでした。
nut数が偶数の時にエラー出すようにしています。
import { z } from "zod";
import { getSemigroup } from "fp-ts/lib/Array";
import { Either, isLeft as isError } from "fp-ts/lib/Either";
import { TaskEither, tryCatch } from "fp-ts/lib/TaskEither";
import { sequenceT } from "fp-ts/lib/Apply";
import { ApplyPar } from "fp-ts/lib/Task";
type UserId = number;
class CustomError extends Error {
constructor(message: string, option?: { cause: unknown }) {
super(message, option);
}
}
const CustomErrorDataSchema = z.custom<CustomError>();
type CustomErrorData = z.infer<typeof CustomErrorDataSchema>;
const doN = (n: number): TaskEither<CustomErrorData, UserId> => {
return tryCatch(
async () => {
if (n % 2 === 0) {
return Promise.reject(
new CustomError(`Something went wrong... [${n}]`)
);
}
return n;
},
(e) => e as CustomErrorData
);
};
const isAllError = (results: Either<CustomErrorData, UserId>[]) => {
return results.every((result) => isError(result));
};
const hasSomeError = (results: Either<CustomErrorData, UserId>[]) => {
return results.some((result) => isError(result));
};
const S = getSemigroup<CustomErrorData>();
const collectError = (results: Either<CustomErrorData, UserId>[]) => {
const errors = results
.map((result) => {
if (isError(result)) {
return result.left;
}
})
.filter((item): item is CustomErrorData => !!item);
return S.concat(errors, []);
};
(async () => {
const results = await sequenceT(ApplyPar)(
doN(1),
doN(2),
doN(3),
doN(4),
doN(5)
)();
console.log(`isAllError`, isAllError(results));
console.log(`hasSomeError`, hasSomeError(results));
console.log(collectError(results));
})();
デモコードです。
簡単ですが、以上です。