Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save freddie-freeloader/4cbc8a8fb26888f411c6b64ee74381c9 to your computer and use it in GitHub Desktop.
Save freddie-freeloader/4cbc8a8fb26888f411c6b64ee74381c9 to your computer and use it in GitHub Desktop.
import { z } from 'zod'
import { mapValues, omit, pick } from 'lodash'
function partialSafeParse<Schema extends z.ZodObject<any>> ( schema: Schema, input: unknown ) {
const result = schema.safeParse( input )
if ( result.success ) return result
const { fieldErrors, formErrors } = result.error.flatten()
if ( formErrors.length ) return result
const inputObj = input as z.infer<Schema>
const keysWithInvalidData = Object.keys( fieldErrors )
const validInput = omit( inputObj, keysWithInvalidData )
const invalidData = pick( inputObj, keysWithInvalidData )
const validData = schema
.omit( mapValues( fieldErrors, () => true as const ) )
.parse( validInput )
return {
success: 'partial',
validData,
invalidData,
fieldErrors,
}
}
// TODO: [WIP} Only works for ZodArray<ZodObject> schemas
export function partialSafeArrayParse<InnerSchema extends z.ZodTypeAny, Schema extends z.ZodArray<InnerSchema>> ( schema: Schema, input: unknown ) {
const result = schema.safeParse( input )
if ( result.success ) return result
const topLevelArray = z.array( z.unknown()).parse( input )
if (schema.element instanceof z.ZodObject) {
// const partialResults = topLevelArray.map( element => partialSafeParse(schema.element, element) )
for (const element of topLevelArray) {
const elementResult = partialSafeParse(schema.element, element)
if (elementResult.success === 'partial') {
return elementResult
}
}
}
}
const userSchema = z.object( { name: z.string(), age: z.number() } )
console.log( partialSafeParse( userSchema, { name: 'foo', age: 42 } ) )
// { success: true, data: { name: "foo", age: 42 } }
console.log( partialSafeParse( userSchema, { name: null, age: 42 } ) )
// {
// success: "partial",
// validData: { age: 42 },
// invalidData: { name: null },
// fieldErrors: { name: [ "Expected string, received null" ] }
// }
console.log( partialSafeParse( userSchema, { name: null } ) )
// {
// success: "partial",
// validData: {},
// invalidData: { name: null },
// fieldErrors: { name: [ "Expected string, received null" ], age: [ "Required" ] }
// }
console.log( partialSafeParse( userSchema, {} ) )
// {
// success: "partial",
// validData: {},
// invalidData: {},
// fieldErrors: { name: [ "Required" ], age: [ "Required" ] }
// }
console.log( partialSafeParse( userSchema, null ) )
// {
// success: false,
// error: ZodError: [
// {
// "code": "invalid_type",
// "expected": "object",
// "received": "null",
// "path": [],
// "message": "Expected object, received null"
// }
// ]
// at handleResult (https://deno.land/x/[email protected]/types.ts:94:19)
// at ZodObject.safeParse (https://deno.land/x/[email protected]/types.ts:231:12)
// at partialSafeParse (file:///C:/_Software/deno-sandbox/zod/mod.ts:16:27)
// at file:///C:/_Software/deno-sandbox/zod/mod.ts:44:14
// }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment