@@ -44,13 +44,27 @@ describe("other vTypes type-arg + optional DX", () => {
4444 > ( ) ;
4545 } ) ;
4646
47+ it ( "v.number accepts optional: true without a type param" , ( ) => {
48+ const field = v . number ( { optional : true } ) ;
49+ expectTypeOf < InferOutput < typeof field > > ( ) . toEqualTypeOf <
50+ number | undefined
51+ > ( ) ;
52+ } ) ;
53+
4754 it ( "v.number with output type param accepts optional: true" , ( ) => {
4855 const field = v . number < number > ( { optional : true } ) ;
4956 expectTypeOf < InferOutput < typeof field > > ( ) . toEqualTypeOf <
5057 number | undefined
5158 > ( ) ;
5259 } ) ;
5360
61+ it ( "v.boolean/date accept optional: true" , ( ) => {
62+ const b = v . boolean ( { optional : true } ) ;
63+ const d = v . date ( { optional : true } ) ;
64+ expectTypeOf < InferOutput < typeof b > > ( ) . toEqualTypeOf < boolean | undefined > ( ) ;
65+ expectTypeOf < InferOutput < typeof d > > ( ) . toEqualTypeOf < Date | undefined > ( ) ;
66+ } ) ;
67+
5468 it ( "v.array with element accepts optional: true" , ( ) => {
5569 const field = v . array ( v . string < "a" | "b" > ( ) , { optional : true } ) ;
5670 expectTypeOf < InferOutput < typeof field > > ( ) . toEqualTypeOf <
@@ -77,6 +91,57 @@ describe("other vTypes type-arg + optional DX", () => {
7791 } ) ;
7892 expectTypeOf < InferOutput < typeof arr > > ( ) . toEqualTypeOf < number [ ] > ( ) ;
7993 } ) ;
94+
95+ it ( "object optional + empty default allows required children" , ( ) => {
96+ const field = v . object (
97+ {
98+ password : v . object (
99+ {
100+ hash : v . string ( { optional : true } ) ,
101+ verify : v . string ( { optional : true } ) ,
102+ } ,
103+ { optional : true , default : { } } ,
104+ ) ,
105+ minPasswordLength : v . number ( ) ,
106+ maxPasswordLength : v . number ( { optional : true } ) ,
107+ } ,
108+ { optional : true , default : { } } ,
109+ ) ;
110+ expectTypeOf < InferOutput < typeof field > > ( ) . toEqualTypeOf < {
111+ password : { hash ?: string ; verify ?: string } ;
112+ minPasswordLength : number ;
113+ maxPasswordLength ?: number ;
114+ } > ( ) ;
115+ } ) ;
116+
117+ it ( "password-options style extend with required number fields" , ( ) => {
118+ const options = v . var ( "options" , { schema : v . object ( { } ) , default : { } } ) ;
119+ const passwordOptions = v . extend ( options , {
120+ emailAndPassword : v . object (
121+ {
122+ password : v . object (
123+ {
124+ hash : v . fn . type ( {
125+ input : { password : v . string ( ) } ,
126+ output : v . string ( ) ,
127+ optional : true ,
128+ } ) ,
129+ verify : v . fn . type ( {
130+ input : { password : v . string ( ) , hash : v . string ( ) } ,
131+ output : v . boolean ( ) ,
132+ optional : true ,
133+ } ) ,
134+ } ,
135+ { optional : true , default : { } } ,
136+ ) ,
137+ minPasswordLength : v . number ( ) ,
138+ maxPasswordLength : v . number ( ) ,
139+ } ,
140+ { optional : true , default : { } } ,
141+ ) ,
142+ } ) ;
143+ expectTypeOf ( passwordOptions ) . not . toBeNever ( ) ;
144+ } ) ;
80145} ) ;
81146
82147describe ( "factory defaults" , ( ) => {
0 commit comments