import { and } from './and.js'; import { Failure, Predicate, Result, Success } from './Predicate.js'; /** * @desc Ensures that the `property` of the `value` meets the `predicates` * * @example * import { ensure, isGreaterThan, property, TinyType } from 'tiny-types'; * * class Name extends TinyType { * constructor(public readonly value: string) { * super(); * ensure('Name', value, property('length', isGreaterThan(3))); * } * } * * @returns {Predicate} */ export function property(propertyName: K, ...predicates: Array>): Predicate { return new HaveProperty(propertyName, and(...predicates)); } /** @access private */ class HaveProperty extends Predicate { constructor(private readonly propertyName: K, private readonly predicate: Predicate) { super(); } /** @override */ check(value: T): Result { const result = this.predicate.check(value[this.propertyName]); return result instanceof Failure ? new Failure(value, `have a property "${ String(this.propertyName) }" that ${ result.description }` .replaceAll(/\bbe\b/gi, 'is') .replaceAll(/\beither is\b/gi, 'is either'), ) : new Success(value); } }