@typed/fp
Version:
Data Structures and Resources for fp-ts
252 lines • 5.22 kB
JavaScript
/**
* Guard is a Typeclass for expressing Refinements
*
* @since 0.9.5
*/
import { identity, pipe } from 'fp-ts/function';
import { memoize } from './Schemable';
// -------------------------------------------------------------------------------------
// constructors
// -------------------------------------------------------------------------------------
/**
* @category constructors
* @since 0.9.5
*/
export const literal = (...values) => ({
is: (u) => values.findIndex((a) => a === u) !== -1,
});
// -------------------------------------------------------------------------------------
// Decoder
// -------------------------------------------------------------------------------------
/**
* @category Decoder
* @since 0.9.5
*/
export const string = {
is: (u) => typeof u === 'string',
};
/**
* Note: `NaN` is excluded.
*
* @category Decoder
* @since 0.9.5
*/
export const number = {
is: (u) => typeof u === 'number' && !isNaN(u),
};
/**
* @category Decoder
* @since 0.9.5
*/
export const boolean = {
is: (u) => typeof u === 'boolean',
};
/**
* @category Decoder
* @since 0.9.5
*/
export const date = {
is: (u) => u instanceof Date,
};
/**
* @category Decoder
* @since 0.9.5
*/
export const unknownArray = {
is: Array.isArray,
};
/**
* @category Decoder
* @since 0.9.5
*/
export const unknownRecord = {
is: (u) => u !== null && typeof u === 'object' && !Array.isArray(u),
};
// -------------------------------------------------------------------------------------
// Combinator
// -------------------------------------------------------------------------------------
/**
* @category Combinator
* @since 0.9.5
*/
export const refine = (refinement) => (from) => ({
is: (i) => from.is(i) && refinement(i),
});
/**
* @category Combinator
* @since 0.9.5
*/
export const nullable = (or) => ({
is: (i) => i === null || or.is(i),
});
/**
* @category Combinator
* @since 2.2.15
*/
export const struct = (properties) => pipe(unknownRecord, refine((r) => {
for (const k in properties) {
if (!(k in r) || !properties[k].is(r[k])) {
return false;
}
}
return true;
}));
/**
* Use `struct` instead.
*
* @category Combinator
* @since 0.9.5
* @deprecated
*/
export const type = struct;
/**
* @category Combinator
* @since 0.9.5
*/
export const partial = (properties) => pipe(unknownRecord, refine((r) => {
for (const k in properties) {
const v = r[k];
if (v !== undefined && !properties[k].is(v)) {
return false;
}
}
return true;
}));
/**
* @category Combinator
* @since 0.9.5
*/
export const array = (item) => pipe(unknownArray, refine((us) => us.every(item.is)));
/**
* @category Combinator
* @since 0.9.5
*/
export const record = (codomain) => pipe(unknownRecord, refine((r) => {
for (const k in r) {
if (!codomain.is(r[k])) {
return false;
}
}
return true;
}));
/**
* @category Combinator
* @since 0.9.5
*/
export const tuple = (...components) => ({
is: (u) => Array.isArray(u) && u.length === components.length && components.every((c, i) => c.is(u[i])),
});
/**
* @category Combinator
* @since 0.9.5
*/
export const intersect = (right) => (left) => ({
is: (u) => left.is(u) && right.is(u),
});
/**
* @category Combinator
* @since 0.9.5
*/
export const union = (second) => (first) => ({
is: (u) => first.is(u) || second.is(u),
});
/**
* @category Combinator
* @since 0.9.5
*/
export const sum = (tag) => (members) => pipe(unknownRecord, refine((r) => {
const v = r[tag];
if (v in members) {
return members[v].is(r);
}
return false;
}));
/**
* @category Combinator
* @since 0.9.5
*/
export const lazy = (f) => {
const get = memoize(f);
return {
is: (u) => get().is(u),
};
};
/**
* @category Combinator
* @since 2.2.15
*/
export const readonly = identity;
/**
* @category Combinator
* @since 0.9.5
*/
export const alt = (that) => (me) => ({
is: (i) => me.is(i) || that().is(i),
});
/**
* @category Combinator
* @since 0.9.5
*/
export const zero = () => ({
is: (_) => false,
});
/**
* @category Combinator
* @since 0.9.5
*/
export const compose = (to) => (from) => ({
is: (i) => from.is(i) && to.is(i),
});
/**
* @category Combinator
* @since 0.9.5
*/
export const id = () => ({
is: (_) => true,
});
// -------------------------------------------------------------------------------------
// instances
// -------------------------------------------------------------------------------------
/**
* @category instances
* @since 0.9.5
*/
export const URI = '@typed/fp/Guard';
/**
* @category instances
* @since 0.9.5
*/
export const Schemable = {
URI,
literal,
string,
number,
boolean,
date,
nullable,
struct,
record,
array,
tuple: tuple,
intersect,
sum,
lazy: (_, f) => lazy(f),
branded: identity,
unknownArray,
unknownRecord,
};
/**
* @category instances
* @since 0.9.5
*/
export const WithUnion = {
union,
};
/**
* @category instances
* @since 0.9.5
*/
export const WithRefine = {
refine: refine,
};
//# sourceMappingURL=Guard.js.map