import is from '@sindresorhus/is'; import {not} from '../operators/not'; export interface Validator { message(value: T): string; validator(value: T): boolean; } export interface Context { validators: Validator[]; } export const validatorSymbol = Symbol('validators'); export class Predicate { constructor( type: string, private context: Context = { validators: [] } ) { this.addValidator({ message: value => `Expected argument to be of type \`${type}\` but received type \`${is(value)}\``, validator: value => is[type](value) }); } get [validatorSymbol]() { return this.context.validators; } /** * Invert the following validators. */ get not(): this { return not(this); } /** * Register a new validator. * * @internal * @param validator Validator to register. */ addValidator(validator: Validator) { this.context.validators.push(validator); return this; } }