When adding/maintaining API validation schemas, make the input contract explicit: specify exactly what input types are accepted, and whether the schema is parsing (strict mapping) or coercing/converting values. Don’t rely on assumptions about built-in JS semantics or on a single runtime’s concrete types.
Apply these rules:
z.string().boolean() does not match Boolean()/MDN behavior—use z.coerce.boolean() when you want JS Boolean()-style coercion.z.date() only for actual Date objects. If the API accepts date strings too, explicitly convert via z.preprocess.size, type, etc.) or create separate schemas per runtime.z.string().min(1) instead of deprecated nonempty).Example (date + boolean semantics):
import { z } from "zod";
// Dates: accept both Date and ISO strings
const dateSchema = z.preprocess((arg) => {
if (typeof arg === "string" || arg instanceof Date) return new Date(arg);
}, z.date());
// Booleans: choose semantics explicitly
const strictLogicalBool = z.string().boolean(); // accepts specific strings like "TRUE"/"False"
const jsBooleanLike = z.coerce.boolean(); // matches JS Boolean() coercion semantics
Enter the URL of a public GitHub repository