1
- import { keysOf , tryCatch , increaseIndent } from './utils' ;
1
+ import { keysOf , tryCatch , primitiveType } from './utils' ;
2
2
import {
3
3
ArrayIndexPathNode ,
4
4
error ,
9
9
success ,
10
10
ValidationError ,
11
11
ValidationResult ,
12
+ EitherValidationError
12
13
} from './validation-result' ;
13
14
export * from './validation-result' ;
14
15
@@ -158,7 +159,7 @@ export function isBoolean(): (arg: any) => ValidationResult<boolean>;
158
159
export function isBoolean < T = boolean > ( next : ( arg : boolean ) => ValidationResult < T > ) : ( arg : any ) => ValidationResult < T > ;
159
160
export function isBoolean ( next ?: ( arg : boolean ) => ValidationResult < any > ) : ( arg : any ) => ValidationResult < any > {
160
161
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 ) } ` ) ;
162
163
return next ? next ( arg ) : success ( arg ) ;
163
164
} ;
164
165
}
@@ -168,7 +169,7 @@ export function isNumber(): (arg: any) => ValidationResult<number>;
168
169
export function isNumber < T = number > ( next : ( arg : number ) => ValidationResult < T > ) : ( arg : any ) => ValidationResult < T > ;
169
170
export function isNumber ( next ?: ( arg : number ) => any ) : ( arg : any ) => ValidationResult < any > {
170
171
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 ) } ` ) ;
172
173
return next ? next ( arg ) : success ( arg ) ;
173
174
} ;
174
175
}
@@ -198,7 +199,7 @@ export function isString(): (arg: any) => ValidationResult<string>;
198
199
export function isString < T = string > ( next : ( arg : string ) => ValidationResult < T > ) : ( arg : any ) => ValidationResult < T > ;
199
200
export function isString ( next ?: ( arg : any ) => ValidationResult < any > ) : ( arg : any ) => ValidationResult < any > {
200
201
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 ) } ` ) ;
202
203
return next ? next ( arg ) : success ( arg ) ;
203
204
} ;
204
205
}
@@ -248,7 +249,7 @@ export function isArray(): (arg: any) => ValidationResult<any[]>;
248
249
export function isArray < T > ( next : ( arg : any [ ] ) => ValidationResult < T > ) : ( arg : any ) => ValidationResult < T > ;
249
250
export function isArray ( next ?: ( arg : any [ ] ) => ValidationResult < any > ) : ( arg : any ) => ValidationResult < any > {
250
251
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 ) } ` ) ;
252
253
return next ? next ( arg ) : success ( arg ) ;
253
254
} ;
254
255
}
@@ -286,7 +287,7 @@ export function isObject(): (arg: any) => ValidationResult<any>;
286
287
export function isObject < T > ( next : ( arg : any ) => ValidationResult < T > ) : ( arg : any ) => ValidationResult < T > ;
287
288
export function isObject ( next ?: ( arg : any ) => ValidationResult < any > ) : ( arg : any ) => ValidationResult < any > {
288
289
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 ) } ` ) ;
290
291
return next ? next ( arg ) : success ( arg ) ;
291
292
} ;
292
293
}
@@ -312,7 +313,7 @@ export function isMap(next?: (arg: any) => ValidationResult<any>): (arg: any) =>
312
313
const nonStringKeys = keysOf ( arg ) . filter ( key => typeof key !== 'string' ) ;
313
314
314
315
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 ) } )` ) } ` ) ;
316
317
}
317
318
318
319
return next ? next ( arg ) : success ( arg ) ;
@@ -341,29 +342,54 @@ export function eachValue<T>(assertion: (arg: any) => ValidationResult<T>, next?
341
342
}
342
343
343
344
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 {
354
377
return ( arg : any ) => {
355
- let errors : ValidationError [ ] = [ ] ;
378
+ const eitherError = new EitherValidationError ( ) ;
356
379
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
+ ) ;
359
385
360
386
if ( result . success ) {
361
387
return result ;
362
388
}
363
389
364
- errors = errors . concat ( result . errors ) ;
390
+ eitherError . errors [ option . description ] = result . errors ;
365
391
}
366
392
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 ) ;
368
394
} ;
369
395
}
0 commit comments