Form-Safe Parsing
Problem
Form submissions often arrive as strings, optional fields, and checkboxes. You need typed output without repeating conversion code for every field.
Solution
Use coercion, wrappers, and formatted errors to normalize the form payload in one step.
ts
import { ValidationError, s } from '@vielzeug/spell';
const SignupForm = s.object({
age: s.coerce.number().int().min(18),
email: s.string().email(),
marketing: s.coerce.boolean().default(false),
referralCode: s.string().trim().optional().nullable().required(),
});
const result = SignupForm.safeParse({
age: '29',
email: 'ada@example.com',
marketing: 'true',
referralCode: null,
});
if (result.success) {
console.log(result.data.referralCode);
} else if (ValidationError.is(result.error)) {
console.log(result.error.format());
}Pitfalls
.required()removesundefinedbut keepsnull. That matters after.optional().nullable()chains.s.coerce.boolean()is for loosely typed input at the boundary. Keep your app state typed after parsing.- Call
safeParseAsync()if any nested field usescheckAsync().