configureCoercion
The
configureCoercionfunction is part of Conform's future export. These APIs are experimental and may change in minor versions. Learn more
A factory that creates coerceFormValue and coerceStructure with custom coercion behavior. The default exports of coerceFormValue and coerceStructure are equivalent to calling configureCoercion() with no arguments.
import { configureCoercion } from '@conform-to/zod/v3/future'; // Or '@conform-to/zod/v4/future'
const { coerceFormValue, coerceStructure } = configureCoercion(config);#Parameters
config.stripEmptyString
Optional. Determines what string values are considered "empty" and stripped to undefined during validation. Receives a raw string and returns the string (possibly transformed) or undefined to indicate empty.
This only applies to coerceFormValue. coerceStructure always preserves empty strings. Empty files are always stripped regardless of this setting.
// Default behavior
stripEmptyString: (value) => (value === '' ? undefined : value);
// Trim whitespace and treat whitespace-only as empty
stripEmptyString: (value) => {
const trimmed = value.trim();
return trimmed === '' ? undefined : trimmed;
};config.type
type?: {
number?: (text: string) => number,
boolean?: (text: string) => boolean,
date?: (text: string) => Date,
}Optional. Type-specific string-to-typed-value conversion functions shared between validation and structural modes. Each function takes a string and returns the converted value.
number: default usesNumber()with empty-string guard (returnsNaNfor empty)boolean: default returnstruefor'on', rejects otherwisedate: default usesnew Date()with invalid date check
bigint is not configurable here because it has no NaN-like sentinel for structural mode. Use customize for custom bigint coercion.
config.customize
customize?: (type: ZodType) => ((value: unknown) => unknown) | null;Optional. A per-schema escape hatch. Called for every schema encountered during traversal. Return a coercion function to override the default for that schema, or null to use the default.
The coercion function receives the raw form value directly. This could be a string, File, an array of values for repeated fields, or any other value depending on the schema structure. Empty values are not stripped automatically.
#Returns
An object with two functions:
coerceFormValue(schema): enhances the schema with empty-value stripping and type coercion for validation.coerceStructure(schema): enhances the schema with type coercion only (no validation, no stripping) for reading typed form data.
#Examples
Custom number parsing
Strip commas and handle locale-specific formatting:
import { configureCoercion } from '@conform-to/zod/v3/future'; // Or '@conform-to/zod/v4/future'
import { z } from 'zod';
const { coerceFormValue, coerceStructure } = configureCoercion({
type: {
number: (text) => Number(text.trim().replace(/,/g, '')),
},
});
const schema = z.object({
price: z.number().min(0),
});
const validationSchema = coerceFormValue(schema);
const structuralSchema = coerceStructure(schema);Trimming whitespace
Trim all string values and treat whitespace-only strings as empty:
const { coerceFormValue } = configureCoercion({
stripEmptyString: (value) => {
const trimmed = value.trim();
return trimmed === '' ? undefined : trimmed;
},
});Per-schema coercion with customize
Override coercion for a specific schema, e.g. parsing a JSON-encoded field:
import { configureCoercion } from '@conform-to/zod/v3/future'; // Or '@conform-to/zod/v4/future'
import { z } from 'zod';
const metadata = z.object({
tags: z.array(z.string()),
priority: z.number(),
});
const { coerceFormValue } = configureCoercion({
customize(type) {
if (type === metadata) {
return (value) => {
if (typeof value !== 'string') {
throw new Error('Expected a string value for metadata');
}
return JSON.parse(value);
};
}
return null;
},
});
const schema = coerceFormValue(
z.object({
title: z.string(),
metadata,
}),
);