@typed/io
Version:
Runtime IO type system
32 lines • 1.54 kB
JavaScript
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