@@ -91,27 +91,36 @@ function isZodSchema(schema: AnySchema): schema is z3.ZodTypeAny | z4.$ZodType {
9191 return true ;
9292 }
9393 const internal = schema as unknown as ZodV3Internal | ZodV4Internal ;
94- return ! ! ( internal . _def || internal . _zod ) ;
94+ if ( '_def' in ( internal as object ) ) {
95+ return ! ! ( internal as ZodV3Internal ) . _def ;
96+ }
97+ if ( '_zod' in ( internal as object ) ) {
98+ return ! ! ( internal as ZodV4Internal ) . _zod ;
99+ }
100+ return false ;
95101}
96102
97103function toIssues ( error : unknown ) : StandardSchemaV1 . Issue [ ] | undefined {
98104 if ( error instanceof SchemaError ) {
99- return error . issues ;
105+ return Array . from ( error . issues ) ;
100106 }
101- if ( Array . isArray ( error ) && error . every ( issue => issue && typeof issue === 'object' && 'message' in issue ) ) {
102- return error as StandardSchemaV1 . Issue [ ] ;
107+ if ( Array . isArray ( error ) ) {
108+ const typed = error as unknown [ ] ;
109+ if ( typed . every ( issue => issue && typeof issue === 'object' && 'message' in ( issue as { message ?: unknown } ) ) ) {
110+ return typed as StandardSchemaV1 . Issue [ ] ;
111+ }
103112 }
104113 if ( error && typeof error === 'object' && 'issues' in error && Array . isArray ( ( error as { issues : unknown } ) . issues ) ) {
105- const issues = ( error as { issues : unknown } ) . issues ;
106- if ( issues . every ( issue => issue && typeof issue === 'object' && 'message' in issue ) ) {
114+ const issues = ( error as { issues : unknown [ ] } ) . issues ;
115+ if ( issues . every ( issue => issue && typeof issue === 'object' && 'message' in ( issue as { message ?: unknown } ) ) ) {
107116 return issues as StandardSchemaV1 . Issue [ ] ;
108117 }
109118 }
110119 return undefined ;
111120}
112121
113122// --- Schema construction ---
114- function createStandardObjectFromShape < Shape extends ZodRawShapeCompat > ( shape : Shape ) : AnyObjectSchema {
123+ function createStandardObjectFromShape < Shape extends Record < string , AnySchema > > ( shape : Shape ) : AnyObjectSchema {
115124 const standardSchema : StandardSchemaV1 < ShapeInput < Shape > , ShapeOutput < Shape > > & { _shape : Shape } = {
116125 _shape : shape ,
117126 '~standard' : {
@@ -141,13 +150,12 @@ function createStandardObjectFromShape<Shape extends ZodRawShapeCompat>(shape: S
141150 const result = await safeParseAsync ( propSchema , propValue ) ;
142151
143152 if ( ! result . success ) {
144- const propIssues = toIssues ( result . error ) ;
145- if ( propIssues ?. length ) {
146- for ( const issue of propIssues ) {
147- const path = issue . path ? [ key , ...issue . path ] : [ key ] ;
148- issues . push ( { ...issue , path } ) ;
149- }
150- } else {
153+ const propIssues = toIssues ( result . error ) ?? [ ] ;
154+ for ( const issue of propIssues as StandardSchemaV1 . Issue [ ] ) {
155+ const path = issue . path ? [ key , ...issue . path ] : [ key ] ;
156+ issues . push ( { ...issue , path } ) ;
157+ }
158+ if ( propIssues . length === 0 ) {
151159 issues . push ( {
152160 message : getParseErrorMessage ( result . error ) ,
153161 path : [ key ]
@@ -170,7 +178,7 @@ function createStandardObjectFromShape<Shape extends ZodRawShapeCompat>(shape: S
170178 return standardSchema as unknown as AnyObjectSchema ;
171179}
172180
173- export function objectFromShape ( shape : ZodRawShapeCompat ) : AnyObjectSchema {
181+ export function objectFromShape ( shape : Record < string , AnySchema > ) : AnyObjectSchema {
174182 const values = Object . values ( shape ) ;
175183 if ( values . length === 0 ) return z4mini . object ( { } ) ; // default to v4 Mini
176184
@@ -278,6 +286,14 @@ export function getObjectShape(schema: AnyObjectSchema | undefined): Record<stri
278286 return rawShape ;
279287}
280288
289+ function isRawShapeCompat ( value : unknown ) : value is ZodRawShapeCompat {
290+ if ( typeof value !== 'object' || value === null ) return false ;
291+ if ( isStandardSchema ( value as AnySchema ) ) return false ;
292+ const asV3 = value as ZodV3Internal ;
293+ const asV4 = value as ZodV4Internal ;
294+ return ! asV3 . _def && ! asV4 . _zod ;
295+ }
296+
281297// --- Schema normalization ---
282298/**
283299 * Normalizes a schema to an object schema. Handles both:
@@ -292,48 +308,25 @@ export function normalizeObjectSchema(schema: AnySchema | ZodRawShapeCompat | un
292308 }
293309
294310 // First check if it's a raw shape (Record<string, AnySchema>)
295- // Raw shapes don't have _def or _zod properties and aren't schemas themselves
296- if ( typeof schema === 'object' ) {
297- // Check if it's actually a ZodRawShapeCompat (not a schema instance)
298- // by checking if it lacks schema-like internal properties
299- const asV3 = schema as unknown as ZodV3Internal ;
300- const asV4 = schema as unknown as ZodV4Internal ;
301-
302- // If it's not a schema instance (no _def or _zod), it might be a raw shape
303- if ( ! asV3 . _def && ! asV4 . _zod ) {
304- // Check if all values are schemas (heuristic to confirm it's a raw shape)
305- const values = Object . values ( schema ) ;
306- if (
307- values . length > 0 &&
308- values . every (
309- v =>
310- typeof v === 'object' &&
311- v !== null &&
312- ( ( v as unknown as ZodV3Internal ) . _def !== undefined ||
313- ( v as unknown as ZodV4Internal ) . _zod !== undefined ||
314- ( isStandardSchema ( v as AnySchema ) && ! ! ( v as AnySchema ) [ '~standard' ] ) ||
315- typeof ( v as { parse ?: unknown } ) . parse === 'function' )
316- )
317- ) {
318- return objectFromShape ( schema as ZodRawShapeCompat ) ;
319- }
320- }
311+ if ( isRawShapeCompat ( schema ) ) {
312+ return objectFromShape ( schema ) ;
321313 }
322314
323315 // If we get here, it should be an AnySchema (not a raw shape)
324316 // Check if it's already an object schema
325- if ( isZ4Schema ( schema as AnySchema ) ) {
317+ const maybeSchema = schema as AnySchema ;
318+ if ( isZ4Schema ( maybeSchema ) ) {
326319 // Check if it's a v4 object
327- const v4Schema = schema as unknown as ZodV4Internal ;
320+ const v4Schema = maybeSchema as unknown as ZodV4Internal ;
328321 const def = v4Schema . _zod ?. def ;
329322 if ( def && ( def . typeName === 'object' || def . shape !== undefined ) ) {
330- return schema as AnyObjectSchema ;
323+ return maybeSchema as unknown as AnyObjectSchema ;
331324 }
332- } else if ( isZodSchema ( schema as AnySchema ) ) {
325+ } else if ( isZodSchema ( maybeSchema ) ) {
333326 // Check if it's a v3 object
334- const v3Schema = schema as unknown as ZodV3Internal ;
327+ const v3Schema = maybeSchema as unknown as ZodV3Internal ;
335328 if ( v3Schema . shape !== undefined ) {
336- return schema as AnyObjectSchema ;
329+ return maybeSchema as unknown as AnyObjectSchema ;
337330 }
338331 }
339332
0 commit comments