diff --git a/src/engine/to-be.ts b/src/engine/to-be.ts index 2c28027..56574e2 100644 --- a/src/engine/to-be.ts +++ b/src/engine/to-be.ts @@ -3,6 +3,23 @@ import { Predicate } from '../rules'; import { throwTypeError } from './throw-type-error'; import { CasterFn, Guard } from './types'; +const spy = (fn: (...args: Args) => R) => { + let isCalled: boolean = false; + const result = (...args: Args) => { + isCalled = true; + return fn(...args); + }; + + Object.defineProperty(result, 'isCalled', { + get: () => isCalled, + }); + + return result as { + (...args: Args): R; + isCalled: boolean; + }; +}; + export const toBe = ( casterFn: CasterFn, @@ -11,7 +28,11 @@ export const toBe = ) => withName( (value, context, reportError = throwTypeError) => { - const typedValue = casterFn(value, context, reportError); + const spyReportError = spy(reportError); + const typedValue = casterFn(value, context, spyReportError); + + if (spyReportError.isCalled) return typedValue; + if (!predicate(typedValue)) { reportError(`${typeName} expected${context ? ` in ${context}` : ''} but "${value}" received.`, context); return undefined as any as never;