From df7b6774ec1ba4e30eafb96ec8582b8bff364f06 Mon Sep 17 00:00:00 2001 From: Sam Verschueren Date: Fri, 13 Oct 2017 18:43:45 +0200 Subject: [PATCH] Use an object to register a validator - fixes #2 (#6) --- source/lib/predicates/predicate.ts | 28 ++++++++++++++++++++-------- source/lib/predicates/string.ts | 20 +++++++------------- source/ow.ts | 11 ++++++----- 3 files changed, 33 insertions(+), 26 deletions(-) diff --git a/source/lib/predicates/predicate.ts b/source/lib/predicates/predicate.ts index 63a8d69..3871ffa 100644 --- a/source/lib/predicates/predicate.ts +++ b/source/lib/predicates/predicate.ts @@ -1,20 +1,32 @@ import * as is from '@sindresorhus/is'; -export type Validator = (value: any) => string | undefined; +export interface Validator { + message: (value: T) => string; + validator: (value: T) => boolean; +} export interface Context { - validators: Validator[]; + validators: Validator[]; } -export class Predicate { +export class Predicate { constructor( type: string, - public context: Context = { validators: [] } + private context: Context = { validators: [] } ) { - this.context.validators.push(value => { - if (!is[type](value)) { - return `Expected argument to be of type \`${type}\` but received type \`${is(value)}\``; - } + this.addValidator({ + message: value => `Expected argument to be of type \`${type}\` but received type \`${is(value)}\``, + validator: value => is[type](value) }); } + + get validators() { + return this.context.validators; + } + + protected addValidator(validator: Validator) { + this.context.validators.push(validator); + + return this; + } } diff --git a/source/lib/predicates/string.ts b/source/lib/predicates/string.ts index dd9bfff..6992c2d 100644 --- a/source/lib/predicates/string.ts +++ b/source/lib/predicates/string.ts @@ -1,6 +1,6 @@ import { Predicate, Context } from './predicate'; -export class StringPredicate extends Predicate { +export class StringPredicate extends Predicate { constructor(context?: Context) { super('string', context); @@ -12,25 +12,19 @@ export class StringPredicate extends Predicate { * @param number The minimum length of the string. */ minLength(number: number) { - this.context.validators.push(value => { - if (value.length < number) { - return `Expected string length to be minimum ${number}`; - } + return this.addValidator({ + message: () => `Expected string length to be minimum ${number}`, + validator: value => value.length >= number }); - - return this; } /** * Test a string to be alphanumeric. */ get alphanumeric() { - this.context.validators.push(value => { - if (!/^[a-z\d]+$/i.test(value)) { - return `Expected string to contain only alphanumeric characters but received \`${value}\``; - } + return this.addValidator({ + message: value => `Expected string to contain only alphanumeric characters but received \`${value}\``, + validator: value => /^[a-z\d]+$/i.test(value) }); - - return this; } } diff --git a/source/ow.ts b/source/ow.ts index 7fd5e72..a83d456 100644 --- a/source/ow.ts +++ b/source/ow.ts @@ -12,13 +12,14 @@ export interface Ow { } export const ow: Ow = (value: any, predicate: Predicate) => { - for (const validator of predicate.context.validators) { - const result = validator(value); - if (result) { + for (const { validator, message } of predicate.validators) { + if (!validator(value)) { // TODO: Modify the stack output to show the original `ow()` call instead of this `throw` statement - throw new ArgumentError(result, ow); + throw new ArgumentError(message(value), ow); } } }; -ow.string = new StringPredicate(); +Object.defineProperty(ow, 'string', { + get: () => new StringPredicate() +});