io-ts-extra
Version:
Adds pattern matching, optional properties, and several other helpers and types, to io-ts.
58 lines • 2.1 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.narrow = void 0;
const io_ts_1 = require("io-ts");
const Either_1 = require("fp-ts/lib/Either");
const chain = Either_1.either.chain;
/**
* Like io-ts's refinement type but:
* 1. Not deprecated (see https://github.com/gcanti/io-ts/issues/373)
* 2. Passes in `Context` to the predicate argument, so you can check parent key names etc.
* 3. Optionally allows returning another io-ts codec instead of a boolean for better error messages.
*
* @example
* const CloudResources = narrow(
* t.type({
* database: t.type({username: t.string, password: t.string}),
* service: t.type({dbConnectionString: t.string}),
* }),
* ({database}) => t.type({
* service: t.type({dbConnectionString: t.literal(`${database.username}:${database.password}`)}),
* })
* )
*
* const valid = CloudResources.decode({
* database: {username: 'user', password: 'pass'},
* service: {dbConnectionString: 'user:pass'},
* })
* // returns a `Right`
*
* const invalid = CloudResources.decode({
* database: {username: 'user', password: 'pass'},
* service: {dbConnectionString: 'user:wrongpassword'},
* })
* // returns a `Left` - service.dbConnectionString expected "user:pass", but got "user:wrongpassword"
*/
const narrow = (codec, predicate, name = `(${codec.name} | ${io_ts_1.getFunctionName(predicate)})`) => {
return new io_ts_1.RefinementType(name, (u) => {
if (!codec.is(u)) {
return false;
}
const refined = predicate(u, []);
if (refined instanceof io_ts_1.Type) {
return refined.is(u);
}
return refined;
}, (i, c) => chain(codec.validate(i, c), a => {
const refined = predicate(a, c);
if (refined instanceof io_ts_1.Type) {
return refined.validate(a, c);
}
if (refined) {
return io_ts_1.success(a);
}
return io_ts_1.failure(a, c);
}), codec.encode, codec, predicate);
};
exports.narrow = narrow;
//# sourceMappingURL=narrow.js.map