diff --git a/source/index.ts b/source/index.ts index 024b4c0..bdcadc3 100644 --- a/source/index.ts +++ b/source/index.ts @@ -201,12 +201,15 @@ export interface Ow { any(...predicate: BasePredicate[]): AnyPredicate; } -const main = (value: T, labelOrPredicate: BasePredicate | string | undefined, predicate?: BasePredicate) => { +const main = (value: T, labelOrPredicate: BasePredicate | string | Function | undefined, predicate?: BasePredicate) => { let label: any = labelOrPredicate; let testPredicate: any = predicate; if (isPredicate(labelOrPredicate)) { - label = inferLabel(callsites()); + const stackFrames = callsites(); + + // Pass in a label function to only infer it when it fails + label = () => inferLabel(stackFrames); testPredicate = labelOrPredicate; } @@ -227,7 +230,9 @@ Object.defineProperties(main, { create: { value: (labelOrPredicate: BasePredicate | string | undefined, predicate?: BasePredicate) => (value: T) => { if (isPredicate(labelOrPredicate)) { - return main(value, inferLabel(callsites()), labelOrPredicate); + const stackFrames = callsites(); + + return main(value, () => inferLabel(stackFrames), labelOrPredicate); } return main(value, labelOrPredicate, predicate); diff --git a/source/lib/predicates/predicate.ts b/source/lib/predicates/predicate.ts index 2d1384b..0d31c46 100644 --- a/source/lib/predicates/predicate.ts +++ b/source/lib/predicates/predicate.ts @@ -55,18 +55,26 @@ export class Predicate implements BasePredicate { * @hidden */ // tslint:disable completed-docs - [testSymbol](value: T, main: Ow, label?: string) { - const label2 = label - ? `${this.type} \`${label}\`` - : this.type; - + [testSymbol](value: T, main: Ow, label?: string | Function) { for (const {validator, message} of this.context.validators) { const result = validator(value); - if (typeof result !== 'boolean' || !result) { - // TODO: Modify the stack output to show the original `ow()` call instead of this `throw` statement - throw new ArgumentError(message(value, label2, result), main); + if (result === true) { + continue; + } + + let label2 = label; + + if (typeof label === 'function') { + label2 = label(); } + + label2 = label2 + ? `${this.type} \`${label2}\`` + : this.type; + + // TODO: Modify the stack output to show the original `ow()` call instead of this `throw` statement + throw new ArgumentError(message(value, label2, result), main); } }