1- import { keysOf , tryCatch , increaseIndent } from './utils' ;
1+ import { keysOf , tryCatch , primitiveType } from './utils' ;
22import {
33 ArrayIndexPathNode ,
44 error ,
99 success ,
1010 ValidationError ,
1111 ValidationResult ,
12+ EitherValidationError
1213} from './validation-result' ;
1314export * from './validation-result' ;
1415
@@ -158,7 +159,7 @@ export function isBoolean(): (arg: any) => ValidationResult<boolean>;
158159export function isBoolean < T = boolean > ( next : ( arg : boolean ) => ValidationResult < T > ) : ( arg : any ) => ValidationResult < T > ;
159160export function isBoolean ( next ?: ( arg : boolean ) => ValidationResult < any > ) : ( arg : any ) => ValidationResult < any > {
160161 return ( arg : any ) => {
161- if ( typeof arg !== 'boolean' ) return error ( 'NOT_BOOLEAN' , `Expected boolean, got ${ typeof arg } ` ) ;
162+ if ( typeof arg !== 'boolean' ) return error ( 'NOT_BOOLEAN' , `Expected boolean, got ${ primitiveType ( arg ) } ` ) ;
162163 return next ? next ( arg ) : success ( arg ) ;
163164 } ;
164165}
@@ -168,7 +169,7 @@ export function isNumber(): (arg: any) => ValidationResult<number>;
168169export function isNumber < T = number > ( next : ( arg : number ) => ValidationResult < T > ) : ( arg : any ) => ValidationResult < T > ;
169170export function isNumber ( next ?: ( arg : number ) => any ) : ( arg : any ) => ValidationResult < any > {
170171 return ( arg : any ) => {
171- if ( typeof arg !== 'number' ) return error ( 'NOT_NUMBER' , `Expected number, got ${ typeof arg } ` ) ;
172+ if ( typeof arg !== 'number' ) return error ( 'NOT_NUMBER' , `Expected number, got ${ primitiveType ( arg ) } ` ) ;
172173 return next ? next ( arg ) : success ( arg ) ;
173174 } ;
174175}
@@ -198,7 +199,7 @@ export function isString(): (arg: any) => ValidationResult<string>;
198199export function isString < T = string > ( next : ( arg : string ) => ValidationResult < T > ) : ( arg : any ) => ValidationResult < T > ;
199200export function isString ( next ?: ( arg : any ) => ValidationResult < any > ) : ( arg : any ) => ValidationResult < any > {
200201 return ( arg : any ) => {
201- if ( typeof arg !== 'string' ) return error ( 'NOT_STRING' , `Expected string, got ${ typeof arg } ` ) ;
202+ if ( typeof arg !== 'string' ) return error ( 'NOT_STRING' , `Expected string, got ${ primitiveType ( arg ) } ` ) ;
202203 return next ? next ( arg ) : success ( arg ) ;
203204 } ;
204205}
@@ -248,7 +249,7 @@ export function isArray(): (arg: any) => ValidationResult<any[]>;
248249export function isArray < T > ( next : ( arg : any [ ] ) => ValidationResult < T > ) : ( arg : any ) => ValidationResult < T > ;
249250export function isArray ( next ?: ( arg : any [ ] ) => ValidationResult < any > ) : ( arg : any ) => ValidationResult < any > {
250251 return ( arg : any ) => {
251- if ( ! ( arg instanceof Array ) ) return error ( 'NOT_ARRAY' , `Expected array, got ${ typeof arg } ` ) ;
252+ if ( ! ( arg instanceof Array ) ) return error ( 'NOT_ARRAY' , `Expected array, got ${ primitiveType ( arg ) } ` ) ;
252253 return next ? next ( arg ) : success ( arg ) ;
253254 } ;
254255}
@@ -286,7 +287,7 @@ export function isObject(): (arg: any) => ValidationResult<any>;
286287export function isObject < T > ( next : ( arg : any ) => ValidationResult < T > ) : ( arg : any ) => ValidationResult < T > ;
287288export function isObject ( next ?: ( arg : any ) => ValidationResult < any > ) : ( arg : any ) => ValidationResult < any > {
288289 return ( arg : any ) => {
289- if ( typeof arg !== 'object' || arg instanceof Array ) return error ( 'NOT_OBJECT' , `Expected object, got ${ arg instanceof Array ? 'array' : typeof arg } ` ) ;
290+ if ( typeof arg !== 'object' || arg instanceof Array ) return error ( 'NOT_OBJECT' , `Expected object, got ${ primitiveType ( arg ) } ` ) ;
290291 return next ? next ( arg ) : success ( arg ) ;
291292 } ;
292293}
@@ -312,7 +313,7 @@ export function isMap(next?: (arg: any) => ValidationResult<any>): (arg: any) =>
312313 const nonStringKeys = keysOf ( arg ) . filter ( key => typeof key !== 'string' ) ;
313314
314315 if ( nonStringKeys . length > 0 ) {
315- return error ( 'NOT_STRING_KEY' , `Expected string keys, got: ${ nonStringKeys . map ( key => `${ key } (${ typeof key } )` ) } ` ) ;
316+ return error ( 'NOT_STRING_KEY' , `Expected string keys, got: ${ nonStringKeys . map ( key => `${ key } (${ primitiveType ( arg ) } )` ) } ` ) ;
316317 }
317318
318319 return next ? next ( arg ) : success ( arg ) ;
@@ -341,29 +342,54 @@ export function eachValue<T>(assertion: (arg: any) => ValidationResult<T>, next?
341342}
342343
343344
344- export function either < A , B > ( assertion1 : ( arg : any ) => ValidationResult < A > , assertion2 : ( arg : any ) => ValidationResult < B > ) : ( arg : any ) => ValidationResult < A | B > ;
345- export function either < A , B , C > ( assertion1 : ( arg : any ) => ValidationResult < A > , assertion2 : ( arg : any ) => ValidationResult < B > , assertion3 : ( arg : any ) => ValidationResult < C > ) : ( arg : any ) => ValidationResult < A | B | C > ;
346- export function either < A , B , C , D > ( assertion1 : ( arg : any ) => ValidationResult < A > , assertion2 : ( arg : any ) => ValidationResult < B > , assertion3 : ( arg : any ) => ValidationResult < C > , assertion4 : ( arg : any ) => ValidationResult < D > ) : ( arg : any ) => ValidationResult < A | B | C | D > ;
347- export function either < A , B , C , D , E > ( assertion1 : ( arg : any ) => ValidationResult < A > , assertion2 : ( arg : any ) => ValidationResult < B > , assertion3 : ( arg : any ) => ValidationResult < C > , assertion4 : ( arg : any ) => ValidationResult < D > , assertion5 : ( arg : any ) => ValidationResult < E > ) : ( arg : any ) => ValidationResult < A | B | C | D | E > ;
348- export function either < A , B , C , D , E , F > ( assertion1 : ( arg : any ) => ValidationResult < A > , assertion2 : ( arg : any ) => ValidationResult < B > , assertion3 : ( arg : any ) => ValidationResult < C > , assertion4 : ( arg : any ) => ValidationResult < D > , assertion5 : ( arg : any ) => ValidationResult < E > , assertion6 : ( arg : any ) => ValidationResult < F > ) : ( arg : any ) => ValidationResult < A | B | C | D | E | F > ;
349- export function either < A , B , C , D , E , F , G > ( assertion1 : ( arg : any ) => ValidationResult < A > , assertion2 : ( arg : any ) => ValidationResult < B > , assertion3 : ( arg : any ) => ValidationResult < C > , assertion4 : ( arg : any ) => ValidationResult < D > , assertion5 : ( arg : any ) => ValidationResult < E > , assertion6 : ( arg : any ) => ValidationResult < F > , assertion7 : ( arg : any ) => ValidationResult < G > ) : ( arg : any ) => ValidationResult < A | B | C | D | E | F | G > ;
350- export function either < A , B , C , D , E , F , G , H > ( assertion1 : ( arg : any ) => ValidationResult < A > , assertion2 : ( arg : any ) => ValidationResult < B > , assertion3 : ( arg : any ) => ValidationResult < C > , assertion4 : ( arg : any ) => ValidationResult < D > , assertion5 : ( arg : any ) => ValidationResult < E > , assertion6 : ( arg : any ) => ValidationResult < F > , assertion7 : ( arg : any ) => ValidationResult < G > , assertion8 : ( arg : any ) => ValidationResult < H > ) : ( arg : any ) => ValidationResult < A | B | C | D | E | F | G | H > ;
351- export function either < A , B , C , D , E , F , G , H , I > ( assertion1 : ( arg : any ) => ValidationResult < A > , assertion2 : ( arg : any ) => ValidationResult < B > , assertion3 : ( arg : any ) => ValidationResult < C > , assertion4 : ( arg : any ) => ValidationResult < D > , assertion5 : ( arg : any ) => ValidationResult < E > , assertion6 : ( arg : any ) => ValidationResult < F > , assertion7 : ( arg : any ) => ValidationResult < G > , assertion8 : ( arg : any ) => ValidationResult < H > , assertion9 : ( arg : any ) => ValidationResult < I > ) : ( arg : any ) => ValidationResult < A | B | C | D | E | F | G | H | I > ;
352- export function either < A , B , C , D , E , F , G , H , I , J > ( assertion1 : ( arg : any ) => ValidationResult < A > , assertion2 : ( arg : any ) => ValidationResult < B > , assertion3 : ( arg : any ) => ValidationResult < C > , assertion4 : ( arg : any ) => ValidationResult < D > , assertion5 : ( arg : any ) => ValidationResult < E > , assertion6 : ( arg : any ) => ValidationResult < F > , assertion7 : ( arg : any ) => ValidationResult < G > , assertion8 : ( arg : any ) => ValidationResult < H > , assertion9 : ( arg : any ) => ValidationResult < I > , assertion10 : ( arg : any ) => ValidationResult < J > ) : ( arg : any ) => ValidationResult < A | B | C | D | E | F | G | H | I | J > ;
353- export function either ( ...assertions : Array < ( arg : any ) => any > ) : ( arg : any ) => any {
345+ export interface IEitherOption < T > {
346+ description : string ;
347+ assertion : ( arg : any ) => ValidationResult < T > ;
348+ }
349+
350+
351+ export function is < T > ( description : string , assertion : ( arg : any ) => ValidationResult < T > ) : IEitherOption < T > {
352+ return { description, assertion} ;
353+ }
354+
355+
356+ // These overloads are necessary for type safety
357+ export function either < A , B > ( option1 : IEitherOption < A > , option2 : IEitherOption < B > ) : ( arg : any ) => ValidationResult < A | B > ;
358+ export function either < A , B , C > ( option1 : IEitherOption < A > , option2 : IEitherOption < B > , option3 : IEitherOption < C > ) : ( arg : any ) => ValidationResult < A | B | C > ;
359+ export function either < A , B , C , D > ( option1 : IEitherOption < A > , option2 : IEitherOption < B > , option3 : IEitherOption < C > , option4 : IEitherOption < D > ) : ( arg : any ) => ValidationResult < A | B | C | D > ;
360+ export function either < A , B , C , D , E > ( option1 : IEitherOption < A > , option2 : IEitherOption < B > , option3 : IEitherOption < C > , option4 : IEitherOption < D > , option5 : IEitherOption < E > ) : ( arg : any ) => ValidationResult < A | B | C | D | E > ;
361+ export function either < A , B , C , D , E , F > ( option1 : IEitherOption < A > , option2 : IEitherOption < B > , option3 : IEitherOption < C > , option4 : IEitherOption < D > , option5 : IEitherOption < E > , option6 : IEitherOption < F > ) : ( arg : any ) => ValidationResult < A | B | C | D | E | F > ;
362+ export function either < A , B , C , D , E , F , G > ( option1 : IEitherOption < A > , option2 : IEitherOption < B > , option3 : IEitherOption < C > , option4 : IEitherOption < D > , option5 : IEitherOption < E > , option6 : IEitherOption < F > , option7 : IEitherOption < G > ) : ( arg : any ) => ValidationResult < A | B | C | D | E | F | G > ;
363+ export function either < A , B , C , D , E , F , G , H > ( option1 : IEitherOption < A > , option2 : IEitherOption < B > , option3 : IEitherOption < C > , option4 : IEitherOption < D > , option5 : IEitherOption < E > , option6 : IEitherOption < F > , option7 : IEitherOption < G > , option8 : IEitherOption < H > ) : ( arg : any ) => ValidationResult < A | B | C | D | E | F | G | H > ;
364+ export function either < A , B , C , D , E , F , G , H , I > ( option1 : IEitherOption < A > , option2 : IEitherOption < B > , option3 : IEitherOption < C > , option4 : IEitherOption < D > , option5 : IEitherOption < E > , option6 : IEitherOption < F > , option7 : IEitherOption < G > , option8 : IEitherOption < H > , option9 : IEitherOption < I > ) : ( arg : any ) => ValidationResult < A | B | C | D | E | F | G | H | I > ;
365+ export function either < A , B , C , D , E , F , G , H , I , J > ( option1 : IEitherOption < A > , option2 : IEitherOption < B > , option3 : IEitherOption < C > , option4 : IEitherOption < D > , option5 : IEitherOption < E > , option6 : IEitherOption < F > , option7 : IEitherOption < G > , option8 : IEitherOption < H > , option9 : IEitherOption < I > , option10 : IEitherOption < J > ) : ( arg : any ) => ValidationResult < A | B | C | D | E | F | G | H | I | J > ;
366+ export function either < A , B , C , D , E , F , G , H , I , J , K > ( option1 : IEitherOption < A > , option2 : IEitherOption < B > , option3 : IEitherOption < C > , option4 : IEitherOption < D > , option5 : IEitherOption < E > , option6 : IEitherOption < F > , option7 : IEitherOption < G > , option8 : IEitherOption < H > , option9 : IEitherOption < I > , option10 : IEitherOption < J > , option11 : IEitherOption < K > ) : ( arg : any ) => ValidationResult < A | B | C | D | E | F | G | H | I | J | K > ;
367+ export function either < A , B , C , D , E , F , G , H , I , J , K , L > ( option1 : IEitherOption < A > , option2 : IEitherOption < B > , option3 : IEitherOption < C > , option4 : IEitherOption < D > , option5 : IEitherOption < E > , option6 : IEitherOption < F > , option7 : IEitherOption < G > , option8 : IEitherOption < H > , option9 : IEitherOption < I > , option10 : IEitherOption < J > , option11 : IEitherOption < K > , option12 : IEitherOption < L > ) : ( arg : any ) => ValidationResult < A | B | C | D | E | F | G | H | I | J | K | L > ;
368+ export function either < A , B , C , D , E , F , G , H , I , J , K , L , M > ( option1 : IEitherOption < A > , option2 : IEitherOption < B > , option3 : IEitherOption < C > , option4 : IEitherOption < D > , option5 : IEitherOption < E > , option6 : IEitherOption < F > , option7 : IEitherOption < G > , option8 : IEitherOption < H > , option9 : IEitherOption < I > , option10 : IEitherOption < J > , option11 : IEitherOption < K > , option12 : IEitherOption < L > , option13 : IEitherOption < M > ) : ( arg : any ) => ValidationResult < A | B | C | D | E | F | G | H | I | J | K | L | M > ;
369+ export function either < A , B , C , D , E , F , G , H , I , J , K , L , M , N > ( option1 : IEitherOption < A > , option2 : IEitherOption < B > , option3 : IEitherOption < C > , option4 : IEitherOption < D > , option5 : IEitherOption < E > , option6 : IEitherOption < F > , option7 : IEitherOption < G > , option8 : IEitherOption < H > , option9 : IEitherOption < I > , option10 : IEitherOption < J > , option11 : IEitherOption < K > , option12 : IEitherOption < L > , option13 : IEitherOption < M > , option14 : IEitherOption < N > ) : ( arg : any ) => ValidationResult < A | B | C | D | E | F | G | H | I | J | K | L | M | N > ;
370+ export function either < A , B , C , D , E , F , G , H , I , J , K , L , M , N , O > ( option1 : IEitherOption < A > , option2 : IEitherOption < B > , option3 : IEitherOption < C > , option4 : IEitherOption < D > , option5 : IEitherOption < E > , option6 : IEitherOption < F > , option7 : IEitherOption < G > , option8 : IEitherOption < H > , option9 : IEitherOption < I > , option10 : IEitherOption < J > , option11 : IEitherOption < K > , option12 : IEitherOption < L > , option13 : IEitherOption < M > , option14 : IEitherOption < N > , option15 : IEitherOption < O > ) : ( arg : any ) => ValidationResult < A | B | C | D | E | F | G | H | I | J | K | L | M | N | O > ;
371+ export function either < A , B , C , D , E , F , G , H , I , J , K , L , M , N , O , P > ( option1 : IEitherOption < A > , option2 : IEitherOption < B > , option3 : IEitherOption < C > , option4 : IEitherOption < D > , option5 : IEitherOption < E > , option6 : IEitherOption < F > , option7 : IEitherOption < G > , option8 : IEitherOption < H > , option9 : IEitherOption < I > , option10 : IEitherOption < J > , option11 : IEitherOption < K > , option12 : IEitherOption < L > , option13 : IEitherOption < M > , option14 : IEitherOption < N > , option15 : IEitherOption < O > , option16 : IEitherOption < P > ) : ( arg : any ) => ValidationResult < A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P > ;
372+ export function either < A , B , C , D , E , F , G , H , I , J , K , L , M , N , O , P , Q > ( option1 : IEitherOption < A > , option2 : IEitherOption < B > , option3 : IEitherOption < C > , option4 : IEitherOption < D > , option5 : IEitherOption < E > , option6 : IEitherOption < F > , option7 : IEitherOption < G > , option8 : IEitherOption < H > , option9 : IEitherOption < I > , option10 : IEitherOption < J > , option11 : IEitherOption < K > , option12 : IEitherOption < L > , option13 : IEitherOption < M > , option14 : IEitherOption < N > , option15 : IEitherOption < O > , option16 : IEitherOption < P > , option17 : IEitherOption < Q > ) : ( arg : any ) => ValidationResult < A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q > ;
373+ export function either < A , B , C , D , E , F , G , H , I , J , K , L , M , N , O , P , Q , R > ( option1 : IEitherOption < A > , option2 : IEitherOption < B > , option3 : IEitherOption < C > , option4 : IEitherOption < D > , option5 : IEitherOption < E > , option6 : IEitherOption < F > , option7 : IEitherOption < G > , option8 : IEitherOption < H > , option9 : IEitherOption < I > , option10 : IEitherOption < J > , option11 : IEitherOption < K > , option12 : IEitherOption < L > , option13 : IEitherOption < M > , option14 : IEitherOption < N > , option15 : IEitherOption < O > , option16 : IEitherOption < P > , option17 : IEitherOption < Q > , option18 : IEitherOption < R > ) : ( arg : any ) => ValidationResult < A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R > ;
374+ export function either < A , B , C , D , E , F , G , H , I , J , K , L , M , N , O , P , Q , R , S > ( option1 : IEitherOption < A > , option2 : IEitherOption < B > , option3 : IEitherOption < C > , option4 : IEitherOption < D > , option5 : IEitherOption < E > , option6 : IEitherOption < F > , option7 : IEitherOption < G > , option8 : IEitherOption < H > , option9 : IEitherOption < I > , option10 : IEitherOption < J > , option11 : IEitherOption < K > , option12 : IEitherOption < L > , option13 : IEitherOption < M > , option14 : IEitherOption < N > , option15 : IEitherOption < O > , option16 : IEitherOption < P > , option17 : IEitherOption < Q > , option18 : IEitherOption < R > , option19 : IEitherOption < S > ) : ( arg : any ) => ValidationResult < A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S > ;
375+ export function either < A , B , C , D , E , F , G , H , I , J , K , L , M , N , O , P , Q , R , S , T > ( option1 : IEitherOption < A > , option2 : IEitherOption < B > , option3 : IEitherOption < C > , option4 : IEitherOption < D > , option5 : IEitherOption < E > , option6 : IEitherOption < F > , option7 : IEitherOption < G > , option8 : IEitherOption < H > , option9 : IEitherOption < I > , option10 : IEitherOption < J > , option11 : IEitherOption < K > , option12 : IEitherOption < L > , option13 : IEitherOption < M > , option14 : IEitherOption < N > , option15 : IEitherOption < O > , option16 : IEitherOption < P > , option17 : IEitherOption < Q > , option18 : IEitherOption < R > , option19 : IEitherOption < S > , option20 : IEitherOption < T > ) : ( arg : any ) => ValidationResult < A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T > ;
376+ export function either ( ...options : Array < IEitherOption < any > > ) : ( arg : any ) => any {
354377 return ( arg : any ) => {
355- let errors : ValidationError [ ] = [ ] ;
378+ const eitherError = new EitherValidationError ( ) ;
356379
357- for ( const assertion of assertions ) {
358- const result = assertion ( arg ) ;
380+ for ( const option of options ) {
381+ const result = tryCatch (
382+ ( ) => option . assertion ( arg ) ,
383+ ( err ) => errorFromException ( err )
384+ ) ;
359385
360386 if ( result . success ) {
361387 return result ;
362388 }
363389
364- errors = errors . concat ( result . errors ) ;
390+ eitherError . errors [ option . description ] = result . errors ;
365391 }
366392
367- return error ( 'NO_MATCH' , 'No match found - the following assertions failed:\n' + errors . map ( error => increaseIndent ( error . toString ( ) , 2 ) ) . join ( '\n' ) ) ;
393+ return new ErrorResult ( eitherError ) ;
368394 } ;
369395}
0 commit comments