diff --git a/packages/conform-zod/coercion.ts b/packages/conform-zod/coercion.ts index 9c46f335..cc8f45ca 100644 --- a/packages/conform-zod/coercion.ts +++ b/packages/conform-zod/coercion.ts @@ -180,26 +180,29 @@ export function enableTypeCoercion( }); } else if (type instanceof ZodEffects) { if (isFileSchema(type)) { - return preprocess((value) => coerceFile(value), type); + schema = preprocess((value) => coerceFile(value), type); + } else { + schema = new ZodEffects({ + ...type._def, + schema: enableTypeCoercion(type.innerType(), cache), + }); } - - schema = new ZodEffects({ - ...type._def, - schema: enableTypeCoercion(type.innerType(), cache), - }); } else if (type instanceof ZodOptional) { schema = preprocess( - (value) => coerceString(coerceFile(value)), + (value) => coerceFile(coerceString(value)), new ZodOptional({ ...type._def, innerType: enableTypeCoercion(type.unwrap(), cache), }), ); } else if (type instanceof ZodDefault) { - schema = new ZodDefault({ - ...type._def, - innerType: enableTypeCoercion(type.removeDefault(), cache), - }); + schema = preprocess( + (value) => coerceFile(coerceString(value)), + new ZodDefault({ + ...type._def, + innerType: enableTypeCoercion(type.removeDefault(), cache), + }), + ); } else if (type instanceof ZodIntersection) { schema = new ZodIntersection({ ...type._def, diff --git a/packages/conform-zod/parse.ts b/packages/conform-zod/parse.ts index 1dc378d9..6124e534 100644 --- a/packages/conform-zod/parse.ts +++ b/packages/conform-zod/parse.ts @@ -10,11 +10,11 @@ import { type output, type RefinementCtx, type SafeParseReturnType, + type ZodCustomIssue, type ZodTypeAny, type ZodErrorMap, type IssueData, ZodIssueCode, - ZodCustomIssue, } from 'zod'; import { enableTypeCoercion } from './coercion'; diff --git a/tests/conform-zod.spec.ts b/tests/conform-zod.spec.ts index 71a3a2b7..c14ad4c2 100644 --- a/tests/conform-zod.spec.ts +++ b/tests/conform-zod.spec.ts @@ -667,6 +667,53 @@ test.describe('conform-zod', () => { expect(() => parse(createFormData([]), { schema })).not.toThrow(); }); + test('z.default', () => { + const defaultFile = new File(['hello', 'world'], 'example.txt'); + const defaultDate = new Date(0); + const schema = z.object({ + a: z.string().default('text'), + b: z.number().default(123), + c: z.boolean().default(true), + d: z.date().default(defaultDate), + e: z.instanceof(File).default(defaultFile), + f: z.array(z.string()).default(['foo', 'bar']), + }); + const emptyFile = new File([], ''); + + expect( + parse( + createFormData([ + ['a', ''], + ['b', ''], + ['c', ''], + ['d', ''], + ['e', emptyFile], + ['f', ''], + ]), + { schema }, + ), + ).toEqual({ + intent: 'submit', + payload: { + a: '', + b: '', + c: '', + d: '', + e: emptyFile, + f: '', + }, + value: { + a: 'text', + b: 123, + c: true, + d: defaultDate, + e: defaultFile, + f: ['foo', 'bar'], + }, + error: {}, + }); + }); + test('z.lazy', () => { const category = z.object({ name: z.string({ required_error: 'required' }),