Skip to main content

.optional()

Makes a schema accept undefined in addition to its base type.
import { z } from 'zod';

const schema = z.string().optional();

schema.parse('hello');     // 'hello'
schema.parse(undefined);   // undefined
schema.parse(null);        // throws error

Type Inference

The .optional() modifier affects both input and output types:
const schema = z.string().optional();

type Input = z.input<typeof schema>;   // string | undefined
type Output = z.output<typeof schema>; // string | undefined

Unwrapping

You can remove the optional wrapper using .unwrap():
const optional = z.string().optional();
const base = optional.unwrap(); // ZodString

In Object Schemas

Fields with .optional() can be omitted from objects:
const User = z.object({
  name: z.string(),
  email: z.string().optional(),
});

User.parse({ name: 'John' });                    // Valid
User.parse({ name: 'John', email: undefined });  // Valid
User.parse({ name: 'John', email: '[email protected]' }); // Valid
When a field is .optional(), you can omit it entirely from the object. The field will be undefined in the parsed result.

.exactOptional()

Similar to .optional(), but enforces that undefined must be explicitly present in objects rather than being omitted.
const User = z.object({
  name: z.string(),
  email: z.string().exactOptional(),
});

User.parse({ name: 'John', email: undefined }); // Valid
User.parse({ name: 'John' });                   // Invalid - email must be present

Type Inference

const schema = z.string().exactOptional();

type Input = z.input<typeof schema>;   // string | undefined
type Output = z.output<typeof schema>; // string | undefined

Use Cases

  • .optional(): Use when a field can be omitted from objects
  • .exactOptional(): Use when you want to distinguish between “field not provided” and “field set to undefined”

Chaining with Other Modifiers

// Optional with default
const schema1 = z.string().optional().default('hello');
schema1.parse(undefined); // 'hello'

// Optional with nullable
const schema2 = z.string().optional().nullable();
schema2.parse(undefined); // undefined
schema2.parse(null);      // null

// Transform then optional
const schema3 = z.string()
  .transform(s => s.toUpperCase())
  .optional();

type Input3 = z.input<typeof schema3>;   // string | undefined
type Output3 = z.output<typeof schema3>; // string | undefined

Build docs developers (and LLMs) love