Accept data whose shape is not known at the schema boundary
External or extensible payloads
Zod · Module
z.unknown() defines a schema that accepts any runtime value while inferring TypeScript’s safer unknown type. Use it when input shape is intentionally unrestricted but downstream code must narrow the value before using it.
z.unknown() creates a schema that accepts values of any type and infers the TypeScript type unknown. Unlike any, unknown requires consumers to narrow or validate the value before using type-specific operations. When used as an object property in Zod 4, the property remains required unless another schema explicitly makes it optional.
z.unknown()A Zod schema whose inferred output type is unknown and which accepts values of any runtime type.
unknown.z.unknown() is required in the inferred object shape.unknown type.z.unknown() as an object property does not make that property optional; the key is required in the inferred object type.z.unknown().import { z } from "zod";
const payloadSchema = z.object({
payload: z.unknown(),
});
const result = payloadSchema.parse({ payload: { event: "created" } });
console.log(result.payload);The schema accepts any runtime value for payload, while TypeScript keeps that value typed as unknown until the program narrows it.
External or extensible payloads
Type-safe deferred validation
Generic object fields
z.unknown() and z.any()?z.unknown() accepts values of any runtime type, but its inferred TypeScript type is unknown. This is safer than any because callers must narrow the value before treating it as a specific type.
Follow-up: How would you make an unknown value optional in an object? Wrap the schema with .optional(), such as z.unknown().optional().
z.unknown() make an object property optional?A property defined as z.unknown() is required in the inferred object type in current Zod. The schema accepts any value for that property, including values whose runtime type is not otherwise constrained.
Follow-up: What change matters when migrating from Zod 3? In Zod 4, z.unknown() no longer causes the object key to be inferred as optional.
z.unknown() useful?Use z.unknown() when the value is intentionally unconstrained at the schema boundary but should remain type-safe in TypeScript. After parsing, narrow it with runtime checks or pass it to another Zod schema.
Follow-up: How can an unknown value be constrained later? Compose a more specific schema, such as z.object({...}), and parse or validate the value against that schema.
z.any()z.object()z.optional()z.record()