@@ -53,7 +53,7 @@ Test('Should Intersect 3', () => {
5353 Assert . IsEqual ( D , '1' )
5454 Assert . IsEqual ( E , 1 )
5555} )
56- Test ( 'Should Intersect 3 ' , ( ) => {
56+ Test ( 'Should Intersect 4 ' , ( ) => {
5757 const NumberToString = Type . Codec ( Type . Number ( ) )
5858 . Decode ( ( value ) => value . toString ( ) )
5959 . Encode ( ( value ) => parseFloat ( value ) )
@@ -67,8 +67,137 @@ Test('Should Intersect 3', () => {
6767// ------------------------------------------------------------------
6868// Illogical
6969// ------------------------------------------------------------------
70- Test ( 'Should Intersect 4 ' , ( ) => {
70+ Test ( 'Should Intersect 5 ' , ( ) => {
7171 const T = Type . Intersect ( [ Type . Array ( Type . Null ( ) ) , Type . Number ( ) ] )
7272 Assert . Throws ( ( ) => Value . Decode ( T , 1 ) )
7373 Assert . Throws ( ( ) => Value . Encode ( T , [ null ] ) )
7474} )
75+ // ------------------------------------------------------------------
76+ // Intersect Operand Should Not Break Subsequent Operands
77+ //
78+ // https://github.com/sinclairzx81/typebox/issues/1466
79+ // ------------------------------------------------------------------
80+ Test ( 'Should Intersect 6' , ( ) => {
81+ let C = 0
82+ const T = Type . Codec ( Type . Object ( {
83+ L : Type . String ( ) ,
84+ R : Type . String ( )
85+ } ) )
86+ . Decode ( ( encoded ) => ( `${ encoded . L } :${ encoded . R } ` ) )
87+ . Encode ( ( decoded ) => {
88+ C = C + 1
89+ const [ L , R ] = decoded . split ( ':' ) as [ string , string ]
90+ return { L, R }
91+ } )
92+ const S = Type . Intersect ( [
93+ Type . Object ( { id : T } ) ,
94+ Type . Object ( { id : T } )
95+ ] )
96+ const D = Value . Decode ( S , { id : { L : 'L' , R : 'R' } } )
97+ const E = Value . Encode ( S , D )
98+ // Expect Multiple Calls Per Operand
99+ Assert . IsEqual ( C , 2 )
100+ Assert . IsEqual ( D , { id : 'L:R' } )
101+ Assert . IsEqual ( E , { id : { L : 'L' , R : 'R' } } )
102+ } )
103+ // ------------------------------------------------------------------
104+ // Intersect With Outer Codec
105+ //
106+ // Verifies the outer Intersect-level Codec is applied after merging
107+ // interiors on Decode, and before on Encode.
108+ // ------------------------------------------------------------------
109+ Test ( 'Should Intersect 7' , ( ) => {
110+ const T = Type . Codec ( Type . Intersect ( [
111+ Type . Object ( { x : Type . Number ( ) } ) ,
112+ Type . Object ( { y : Type . Number ( ) } )
113+ ] ) )
114+ . Decode ( ( value ) => ( { ...value , decoded : true } ) )
115+ . Encode ( ( { decoded : _ , ...rest } ) => rest )
116+
117+ const D = Value . Decode ( T , { x : 1 , y : 2 } )
118+ const E = Value . Encode ( T , D )
119+ Assert . IsEqual ( D , { x : 1 , y : 2 , decoded : true } )
120+ Assert . IsEqual ( E , { x : 1 , y : 2 } )
121+ } )
122+ // ------------------------------------------------------------------
123+ // Intersect Key Override
124+ //
125+ // Verifies that when two operands produce the same key, the latter
126+ // operand's value wins on merge.
127+ // ------------------------------------------------------------------
128+ Test ( 'Should Intersect 8' , ( ) => {
129+ const Increment = Type . Codec ( Type . Number ( ) )
130+ . Decode ( ( value ) => value + 1 )
131+ . Encode ( ( value ) => value - 1 )
132+
133+ const T = Type . Intersect ( [
134+ Type . Object ( { n : Type . Number ( ) } ) ,
135+ Type . Object ( { n : Increment } )
136+ ] )
137+ const D = Value . Decode ( T , { n : 1 } )
138+ const E = Value . Encode ( T , D )
139+ Assert . IsEqual ( D , { n : 2 } ) // latter operand wins
140+ Assert . IsEqual ( E , { n : 1 } )
141+ } )
142+ // ------------------------------------------------------------------
143+ // Empty Intersect
144+ //
145+ // Verifies that an Intersect with no operands decodes and encodes
146+ // without error, returning an empty object.
147+ // ------------------------------------------------------------------
148+ Test ( 'Should Intersect 9' , ( ) => {
149+ const T = Type . Intersect ( [ ] )
150+ const D = Value . Decode ( T , { } )
151+ const E = Value . Encode ( T , D )
152+ Assert . IsEqual ( D , { } )
153+ Assert . IsEqual ( E , { } )
154+ } )
155+ // ------------------------------------------------------------------
156+ // Empty Intersect
157+ //
158+ // Verifies that an empty Intersect returns the original value
159+ // unchanged for both Decode and Encode.
160+ // ------------------------------------------------------------------
161+ Test ( 'Should Intersect 10' , ( ) => {
162+ const T = Type . Intersect ( [ ] )
163+ const D = Value . Decode ( T , 42 )
164+ const E = Value . Encode ( T , 42 )
165+ Assert . IsEqual ( D , 42 )
166+ Assert . IsEqual ( E , 42 )
167+ } )
168+ // ------------------------------------------------------------------
169+ // Primitive With No Transformation
170+ //
171+ // Verifies that when no operand transforms the value,
172+ // NonMatchingInterior correctly falls back to the first result.
173+ // ------------------------------------------------------------------
174+ Test ( 'Should Intersect 11' , ( ) => {
175+ const T = Type . Intersect ( [ Type . Number ( ) , Type . Number ( ) ] )
176+ const D = Value . Decode ( T , 42 )
177+ const E = Value . Encode ( T , 42 )
178+ Assert . IsEqual ( D , 42 )
179+ Assert . IsEqual ( E , 42 )
180+ } )
181+ // ------------------------------------------------------------------
182+ // Nested Intersect
183+ //
184+ // Verifies that codec transformation composes correctly when
185+ // Intersect types are nested inside one another.
186+ // ------------------------------------------------------------------
187+ Test ( 'Should Intersect 12' , ( ) => {
188+ const NumberToString = Type . Codec ( Type . Number ( ) )
189+ . Decode ( ( value ) => value . toString ( ) )
190+ . Encode ( ( value ) => parseFloat ( value ) )
191+
192+ const Inner = Type . Intersect ( [
193+ Type . Object ( { x : NumberToString } )
194+ ] )
195+ const Outer = Type . Intersect ( [
196+ Inner ,
197+ Type . Object ( { y : NumberToString } )
198+ ] )
199+ const D = Value . Decode ( Outer , { x : 1 , y : 2 } )
200+ const E = Value . Encode ( Outer , D )
201+ Assert . IsEqual ( D , { x : '1' , y : '2' } )
202+ Assert . IsEqual ( E , { x : 1 , y : 2 } )
203+ } )
0 commit comments