File tree 3 files changed +35
-1
lines changed
3 files changed +35
-1
lines changed Original file line number Diff line number Diff line change @@ -5,7 +5,7 @@ import { VBase } from './base'
5
5
import { VBoolean } from './booleans'
6
6
import { VCore } from './core'
7
7
import { VFile } from './files'
8
- import { VAnd , VOr } from './junctions'
8
+ import { VAnd , VDiscriminator , VOr } from './junctions'
9
9
import { VNumber } from './numbers'
10
10
import { VObject } from './objects'
11
11
import { VMap , VRecord } from './records'
@@ -21,6 +21,7 @@ export const v = {
21
21
or : VBase . createType ( VOr ) ,
22
22
and : VBase . createType ( VAnd ) ,
23
23
string : VBase . createType ( VString ) ,
24
+ discriminate : VBase . createType ( VDiscriminator ) ,
24
25
number : VBase . createType ( VNumber ) ,
25
26
boolean : VBase . createType ( VBoolean ) ,
26
27
time : VBase . createType ( VTime ) ,
Original file line number Diff line number Diff line change @@ -31,4 +31,16 @@ export class VAnd<I> extends VCore<I> {
31
31
return isValid ( v )
32
32
} ) )
33
33
}
34
+ }
35
+
36
+ export class VDiscriminator < D extends Record < string , VCore < any > > > extends VCore < ExtractI < D [ keyof D ] > > {
37
+ constructor ( discriminator : ( val : ExtractI < D [ keyof D ] > ) => string , schemas : D , err = 'doesnt match any of the schema' ) {
38
+ super ( )
39
+ this . addTyping ( makeRule < ExtractI < D [ keyof D ] > > ( ( value ) => {
40
+ const val = value as ExtractI < D [ keyof D ] >
41
+ const accessor = discriminator ( val )
42
+ if ( ! schemas [ accessor ] ) return isInvalid ( [ err ] , val )
43
+ return schemas [ accessor ] . parse ( val )
44
+ } ) )
45
+ }
34
46
}
Original file line number Diff line number Diff line change @@ -23,4 +23,25 @@ describe('and', () => {
23
23
expect ( rules . parse ( '' ) . valid ) . toBe ( false )
24
24
expect ( rules . parse ( false ) . valid ) . toBe ( false )
25
25
} )
26
+ } )
27
+
28
+ describe ( 'discriminate' , ( ) => {
29
+ test ( 'discriminate' , ( ) => {
30
+ const rules = v . discriminate ( ( v ) => v , {
31
+ 'ha' : v . string ( ) ,
32
+ 'make' : v . string ( ) . has ( 4 ) ,
33
+ } )
34
+ expect ( rules . parse ( 'ha' ) . valid ) . toBe ( true )
35
+ expect ( rules . parse ( 2 ) . valid ) . toBe ( false )
36
+ expect ( rules . parse ( 'make' ) . valid ) . toBe ( true )
37
+ expect ( rules . parse ( 'made' ) . valid ) . toBe ( false )
38
+
39
+ const objectRules = v . discriminate ( ( v ) => v . status , {
40
+ 'ha' : v . object ( { status : v . is ( 'ha' ) , total : v . number ( ) . gt ( 10 ) } ) ,
41
+ 'name' : v . object ( { status : v . is ( 'name' ) , flow : v . boolean ( ) } )
42
+ } )
43
+ expect ( objectRules . parse ( { 'status' : 'ha' , total : 12 } ) . valid ) . toBe ( true )
44
+ expect ( objectRules . parse ( { 'status' : 'ha' , total : 9 } ) . valid ) . toBe ( false )
45
+ expect ( objectRules . parse ( { 'status' : 'none' } ) . valid ) . toBe ( false )
46
+ } )
26
47
} )
You can’t perform that action at this time.
0 commit comments