UNPKG

@typed/io

Version:

Runtime IO type system

32 lines 1.54 kB
import { combine, map } from '@typed/effects'; import { fromLeft, fromRight, isLeft, isRight } from '@typed/either'; import { Just } from '@typed/maybe'; import { hasOwnProperty, keysOf, mapToList } from '@typed/objects'; import { toString } from '@typed/strings'; import { catchDecodeFailure, DecodeError, decodeFailure } from './Decoder'; import { Record } from './Record'; import { refinement } from './refinement'; export const partial = (decoders, expected = getDefaultPartialExpected(decoders)) => { const keys = keysOf(decoders); return refinement(Record, function* (r) { const decoded = yield* combine(...keys .filter((k) => hasOwnProperty(k, r)) .map((k) => catchDecodeFailure(map((a) => [a, k], decoders[k].decode(r[k])), () => k))); if (decoded.every(isRight)) { return decoded .map((d) => fromRight(d)) .reduce((acc, [v, k]) => ({ ...acc, [k]: v }), {}); } const errors = decoded.filter(isLeft).map(fromLeft); return yield* decodeFailure(decodePartialError(errors, expected, toString(r))); }, expected); }; function getDefaultPartialExpected(decoders) { return `{\n ${mapToList((key, value) => `"${key.toString()}"?: ${value.expected}`, decoders).join(`,\n `)}\n}`; } function decodePartialError(errors, expected, value) { return DecodeError.create(expected, value, { errors: errors.map(([e, key]) => ({ ...e, key: Just.of(toString(key)) })), }); } //# sourceMappingURL=Partial.js.map