@@ -69,6 +69,17 @@ export interface CastOptions<C = {}> {
69
69
path ?: string ;
70
70
}
71
71
72
+ export interface CastOptionalityOptions < C = { } >
73
+ extends Omit < CastOptions < C > , 'assert' > {
74
+ /**
75
+ * Whether or not to throw TypeErrors if casting fails to produce a valid type.
76
+ * defaults to `true`. The `'ignore-optionality'` options is provided as a migration
77
+ * path from pre-v1 where `schema.nullable().required()` was allowed. When provided
78
+ * cast will only throw for values that are the wrong type *not* including `null` and `undefined`
79
+ */
80
+ assert : 'ignore-optionality' ;
81
+ }
82
+
72
83
export type RunTest = (
73
84
opts : TestOptions ,
74
85
panic : PanicCallback ,
@@ -328,19 +339,33 @@ export default abstract class Schema<
328
339
/**
329
340
* Run the configured transform pipeline over an input value.
330
341
*/
331
- cast ( value : any , options : CastOptions < TContext > = { } ) : this[ '__outputType' ] {
342
+ cast ( value : any , options ?: CastOptions < TContext > ) : this[ '__outputType' ] ;
343
+ cast (
344
+ value : any ,
345
+ options : CastOptionalityOptions < TContext > ,
346
+ ) : this[ '__outputType' ] | null | undefined ;
347
+ cast (
348
+ value : any ,
349
+ options : CastOptions < TContext > | CastOptionalityOptions < TContext > = { } ,
350
+ ) : this[ '__outputType' ] {
332
351
let resolvedSchema = this . resolve ( {
333
352
value,
334
353
...options ,
335
354
// parent: options.parent,
336
355
// context: options.context,
337
356
} ) ;
357
+ let allowOptionality = options . assert === 'ignore-optionality' ;
338
358
339
- let result = resolvedSchema . _cast ( value , options ) ;
359
+ let result = resolvedSchema . _cast ( value , options as any ) ;
340
360
341
361
if ( options . assert !== false && ! resolvedSchema . isType ( result ) ) {
362
+ if ( allowOptionality && isAbsent ( result ) ) {
363
+ return result as any ;
364
+ }
365
+
342
366
let formattedValue = printValue ( value ) ;
343
367
let formattedResult = printValue ( result ) ;
368
+
344
369
throw new TypeError (
345
370
`The value of ${
346
371
options . path || 'field'
@@ -523,8 +548,7 @@ export default abstract class Schema<
523
548
validate (
524
549
value : any ,
525
550
options ?: ValidateOptions < TContext > ,
526
- ) : Promise < this[ '__outputType' ] > ;
527
- validate ( value : any , options ?: ValidateOptions < TContext > ) : any {
551
+ ) : Promise < this[ '__outputType' ] > {
528
552
let schema = this . resolve ( { ...options , value } ) ;
529
553
530
554
return new Promise ( ( resolve , reject ) =>
@@ -537,16 +561,12 @@ export default abstract class Schema<
537
561
} ,
538
562
( errors , validated ) => {
539
563
if ( errors . length ) reject ( new ValidationError ( errors ! , validated ) ) ;
540
- else resolve ( validated ) ;
564
+ else resolve ( validated as this [ '__outputType' ] ) ;
541
565
} ,
542
566
) ,
543
567
) ;
544
568
}
545
569
546
- validateSync (
547
- value : any ,
548
- options ?: ValidateOptions < TContext > ,
549
- ) : this[ '__outputType' ] ;
550
570
validateSync (
551
571
value : any ,
552
572
options ?: ValidateOptions < TContext > ,
0 commit comments