import { isArray } from './isArray.js'; import { isDefined } from './isDefined.js'; import { isGreaterThan } from './isGreaterThan.js'; import { Failure, Predicate, Result, Success } from './Predicate.js'; /** * @desc Ensures that the `value` meets all the provided {@link Predicate}s. * * @example * import { and, ensure, isDefined, isGreaterThan, isInteger, TinyType } from 'tiny-types'; * * class AgeInYears extends TinyType { * constructor(public readonly value: number) { * ensure('AgeInYears', value, and(isDefined(), isInteger(), isGreaterThan(18)); * } * } * * @param {...Array>} predicates * @returns {Predicate} */ export function and(...predicates: Array>): Predicate { return new And(predicates); } /** @access private */ class And extends Predicate { constructor(private readonly predicates: Array>) { super(); const results = [ _ => isDefined().check(_), _ => isArray().check(_), _ => isGreaterThan(0).check(_.length), ]; if (results.some(check => check(this.predicates) instanceof Failure)) { throw new Error(`Looks like you haven't specified any predicates to check the value against?`); } } /** @override */ check(value: T): Result { for (const predicate of this.predicates) { const result = predicate.check(value); if (result instanceof Failure) { return result; } } return new Success(value); } }