@@ -22,12 +22,29 @@ export type ZodObjectV3 = z3.ZodObject<any, any, any, any>;
2222
2323export type ZodObjectV4 = z4 . $ZodObject ;
2424
25+ export type ZodDefaultV3 < T extends z3 . ZodTypeAny > = z3 . ZodDefault < T > ;
26+ export type ZodDefaultV4 < T extends z4 . SomeType > = z4 . $ZodDefault < T > ;
27+ export type ZodOptionalV3 < T extends z3 . ZodTypeAny > = z3 . ZodOptional < T > ;
28+ export type ZodOptionalV4 < T extends z4 . SomeType > = z4 . $ZodOptional < T > ;
29+
2530// eslint-disable-next-line @typescript-eslint/no-explicit-any
2631export type InteropZodType < Output = any , Input = Output > =
2732 | z3 . ZodType < Output , z3 . ZodTypeDef , Input >
2833 | z4 . $ZodType < Output , Input > ;
2934
3035export type InteropZodObject = ZodObjectV3 | ZodObjectV4 ;
36+ export type InteropZodDefault < T = InteropZodObjectShape > =
37+ T extends z3 . ZodTypeAny
38+ ? ZodDefaultV3 < T >
39+ : T extends z4 . SomeType
40+ ? ZodDefaultV4 < T >
41+ : never ;
42+ export type InteropZodOptional < T = InteropZodObjectShape > =
43+ T extends z3 . ZodTypeAny
44+ ? ZodOptionalV3 < T >
45+ : T extends z4 . SomeType
46+ ? ZodOptionalV4 < T >
47+ : never ;
3148
3249export type InteropZodObjectShape <
3350 T extends InteropZodObject = InteropZodObject
@@ -178,7 +195,7 @@ export async function interopSafeParseAsync<T>(
178195 }
179196 }
180197 if ( isZodSchemaV3 ( schema as z3 . ZodType < Record < string , unknown > > ) ) {
181- return schema . safeParse ( input ) ;
198+ return await schema . safeParseAsync ( input ) ;
182199 }
183200 throw new Error ( "Schema must be an instance of z3.ZodType or z4.$ZodType" ) ;
184201}
@@ -198,10 +215,10 @@ export async function interopParseAsync<T>(
198215 input : unknown
199216) : Promise < T > {
200217 if ( isZodSchemaV4 ( schema ) ) {
201- return parse ( schema , input ) ;
218+ return await parseAsync ( schema , input ) ;
202219 }
203220 if ( isZodSchemaV3 ( schema as z3 . ZodType < Record < string , unknown > > ) ) {
204- return schema . parse ( input ) ;
221+ return await schema . parseAsync ( input ) ;
205222 }
206223 throw new Error ( "Schema must be an instance of z3.ZodType or z4.$ZodType" ) ;
207224}
@@ -780,3 +797,67 @@ export function interopZodTransformInputSchema(
780797
781798 throw new Error ( "Schema must be an instance of z3.ZodType or z4.$ZodType" ) ;
782799}
800+
801+ /**
802+ * Creates a modified version of a Zod object schema where fields matching a predicate are made optional.
803+ * Supports both Zod v3 and v4 schemas and preserves the original schema version.
804+ *
805+ * @template T - The type of the Zod object schema.
806+ * @param {T } schema - The Zod object schema instance (either v3 or v4).
807+ * @param {(key: string, value: InteropZodType) => boolean } predicate - Function to determine which fields should be optional.
808+ * @returns {InteropZodObject } The modified Zod object schema.
809+ * @throws {Error } If the schema is not a Zod v3 or v4 object.
810+ */
811+ export function interopZodObjectMakeFieldsOptional < T extends InteropZodObject > (
812+ schema : T ,
813+ predicate : ( key : string , value : InteropZodType ) => boolean
814+ ) : InteropZodObject {
815+ if ( isZodSchemaV3 ( schema ) ) {
816+ const shape = getInteropZodObjectShape ( schema ) ;
817+ const modifiedShape : Record < string , z3 . ZodTypeAny > = { } ;
818+
819+ for ( const [ key , value ] of Object . entries ( shape ) ) {
820+ if ( predicate ( key , value ) ) {
821+ // Make this field optional using v3 methods
822+ modifiedShape [ key ] = ( value as z3 . ZodTypeAny ) . optional ( ) ;
823+ } else {
824+ // Keep field as-is
825+ modifiedShape [ key ] = value ;
826+ }
827+ }
828+
829+ // Use v3's extend method to create a new schema with the modified shape
830+ return schema . extend ( modifiedShape as z3 . ZodRawShape ) ;
831+ }
832+
833+ if ( isZodSchemaV4 ( schema ) ) {
834+ const shape = getInteropZodObjectShape ( schema ) ;
835+ const outputShape : Mutable < z4 . $ZodShape > = { ...schema . _zod . def . shape } ;
836+
837+ for ( const [ key , value ] of Object . entries ( shape ) ) {
838+ if ( predicate ( key , value ) ) {
839+ // Make this field optional using v4 methods
840+ outputShape [ key ] = new $ZodOptional ( {
841+ type : "optional" as const ,
842+ innerType : value as z4 . $ZodType ,
843+ } ) ;
844+ }
845+ // Otherwise keep the field as-is (already in outputShape)
846+ }
847+
848+ const modifiedSchema = clone < ZodObjectV4 > ( schema , {
849+ ...schema . _zod . def ,
850+ shape : outputShape ,
851+ } ) ;
852+
853+ // Preserve metadata
854+ const meta = globalRegistry . get ( schema ) ;
855+ if ( meta ) globalRegistry . add ( modifiedSchema , meta ) ;
856+
857+ return modifiedSchema ;
858+ }
859+
860+ throw new Error (
861+ "Schema must be an instance of z3.ZodObject or z4.$ZodObject"
862+ ) ;
863+ }
0 commit comments