Skip to main content

Basic Usage

Create an object schema by defining the shape of its properties.
import { z } from 'zod';

const UserSchema = z.object({
  id: z.string(),
  name: z.string(),
  email: z.string().email(),
  age: z.number().optional(),
});

type User = z.infer<typeof UserSchema>;
// { id: string; name: string; email: string; age?: number }

Signature

function object<T extends ZodLooseShape>(
  shape?: T,
  params?: string | ZodObjectParams
): ZodObject<T, ZodStrip>
shape
object
An object where each key maps to a Zod schema. Defines the structure of the object.
params
string | ZodObjectParams
Optional error message (string) or configuration object.

Properties

shape
object
Access the object’s shape definition.
const schema = z.object({ name: z.string() });
schema.shape.name; // ZodString

Methods

extend()

Add new properties to an object schema or override existing ones.
const BaseUser = z.object({
  id: z.string(),
  name: z.string(),
});

const ExtendedUser = BaseUser.extend({
  email: z.string().email(),
  createdAt: z.date(),
});

type ExtendedUser = z.infer<typeof ExtendedUser>;
// { id: string; name: string; email: string; createdAt: Date }
When extending an object with refinements, you can only add new properties. Use .safeExtend() to override existing properties.
Signature:
extend<U extends ZodLooseShape>(shape: U): ZodObject<Extend<Shape, U>, Config>
shape
object
required
Object containing additional properties to add or override.

safeExtend()

Safely extend an object schema, allowing property overrides even with refinements.
const schema = z.object({
  id: z.string(),
  name: z.string(),
}).refine(data => data.id.length > 0);

const extended = schema.safeExtend({
  name: z.string().min(3), // Override allowed with safeExtend
  email: z.string().email(),
});
Signature:
safeExtend<U extends ZodLooseShape>(
  shape: SafeExtendShape<Shape, U> & Partial<Record<keyof Shape, SomeType>>
): ZodObject<Extend<Shape, U>, Config>

merge()

Deprecated. Use A.extend(B.shape) instead.
Merge two object schemas together.
const NameSchema = z.object({ name: z.string() });
const AgeSchema = z.object({ age: z.number() });

// Deprecated approach
const PersonSchema = NameSchema.merge(AgeSchema);

// Recommended approach
const PersonSchema = NameSchema.extend(AgeSchema.shape);
Signature:
merge<U extends ZodObject>(
  other: U
): ZodObject<Extend<Shape, U['shape']>, U['_zod']['config']>

pick()

Create a new schema with only the specified properties.
const UserSchema = z.object({
  id: z.string(),
  name: z.string(),
  email: z.string().email(),
  password: z.string(),
});

const PublicUserSchema = UserSchema.pick({
  id: true,
  name: true,
  email: true,
});

type PublicUser = z.infer<typeof PublicUserSchema>;
// { id: string; name: string; email: string }
Cannot be used on object schemas containing refinements. The refinements would apply to the full object, not the picked subset.
Signature:
pick<M extends Mask<keyof Shape>>(
  mask: M & Record<Exclude<keyof M, keyof Shape>, never>
): ZodObject<Flatten<Pick<Shape, Extract<keyof Shape, keyof M>>>, Config>
mask
object
required
Object with keys to pick. Set values to true to include, false to exclude.

omit()

Create a new schema excluding the specified properties.
const UserSchema = z.object({
  id: z.string(),
  name: z.string(),
  email: z.string().email(),
  password: z.string(),
});

const UserWithoutPassword = UserSchema.omit({
  password: true,
});

type SafeUser = z.infer<typeof UserWithoutPassword>;
// { id: string; name: string; email: string }
Cannot be used on object schemas containing refinements.
Signature:
omit<M extends Mask<keyof Shape>>(
  mask: M & Record<Exclude<keyof M, keyof Shape>, never>
): ZodObject<Flatten<Omit<Shape, Extract<keyof Shape, keyof M>>>, Config>
mask
object
required
Object with keys to omit. Set values to true to exclude, false to include.

partial()

Make all properties optional.
const UserSchema = z.object({
  name: z.string(),
  email: z.string().email(),
});

const PartialUserSchema = UserSchema.partial();

type PartialUser = z.infer<typeof PartialUserSchema>;
// { name?: string; email?: string }
You can also make specific properties optional:
const PartiallyOptional = UserSchema.partial({
  email: true,
});

type PartiallyOptional = z.infer<typeof PartiallyOptional>;
// { name: string; email?: string }
Signature:
partial(): ZodObject<{ [k in keyof Shape]: ZodOptional<Shape[k]> }, Config>

partial<M extends Mask<keyof Shape>>(
  mask: M & Record<Exclude<keyof M, keyof Shape>, never>
): ZodObject<{
  [k in keyof Shape]: k extends keyof M ? ZodOptional<Shape[k]> : Shape[k]
}, Config>
mask
object
Optional object specifying which keys to make optional.

required()

Make all properties required (remove optionality).
const OptionalUserSchema = z.object({
  name: z.string().optional(),
  email: z.string().optional(),
});

const RequiredUserSchema = OptionalUserSchema.required();

type RequiredUser = z.infer<typeof RequiredUserSchema>;
// { name: string; email: string }
You can also make specific properties required:
const PartiallyRequired = OptionalUserSchema.required({
  name: true,
});

type PartiallyRequired = z.infer<typeof PartiallyRequired>;
// { name: string; email?: string }
Signature:
required(): ZodObject<{ [k in keyof Shape]: ZodNonOptional<Shape[k]> }, Config>

required<M extends Mask<keyof Shape>>(
  mask: M & Record<Exclude<keyof M, keyof Shape>, never>
): ZodObject<{
  [k in keyof Shape]: k extends keyof M ? ZodNonOptional<Shape[k]> : Shape[k]
}, Config>
mask
object
Optional object specifying which keys to make required.

keyof()

Extract the keys of an object schema as an enum.
const UserSchema = z.object({
  id: z.string(),
  name: z.string(),
  email: z.string(),
});

const UserKey = UserSchema.keyof();

type UserKey = z.infer<typeof UserKey>;
// "id" | "name" | "email"
Signature:
keyof(): ZodEnum<ToEnum<keyof Shape & string>>

catchall()

Define a schema to validate all unrecognized keys.
const FlexibleConfig = z.object({
  host: z.string(),
  port: z.number(),
}).catchall(z.string());

FlexibleConfig.parse({
  host: 'localhost',
  port: 3000,
  debug: 'true',      // Validated as string
  timeout: '5000',    // Validated as string
}); // ✓ Valid

FlexibleConfig.parse({
  host: 'localhost',
  port: 3000,
  maxConnections: 100, // ✗ Invalid - not a string
});
Signature:
catchall<T extends SomeType>(schema: T): ZodObject<Shape, ZodCatchall<T>>
schema
ZodType
required
Schema to validate unrecognized keys against.

passthrough()

Deprecated. Use .loose() or z.looseObject() instead.
Allow unrecognized keys to pass through without validation.
const schema = z.object({ name: z.string() }).passthrough();

loose()

Allow unrecognized keys without validation (replaces .passthrough()).
const schema = z.object({
  id: z.string(),
}).loose();

schema.parse({ id: '123', extra: 'value' }); // ✓ Valid
Signature:
loose(): ZodObject<Shape, ZodLoose>

strict()

Disallow unrecognized keys (fail validation).
const StrictUser = z.object({
  id: z.string(),
  name: z.string(),
}).strict();

StrictUser.parse({ id: '123', name: 'Alice' }); // ✓ Valid

StrictUser.parse({
  id: '123',
  name: 'Alice',
  email: '[email protected]', // ✗ Invalid - unrecognized key
});
Signature:
strict(): ZodObject<Shape, ZodStrict>

strip()

Remove unrecognized keys (default behavior).
const schema = z.object({
  name: z.string(),
}).strip();

const result = schema.parse({
  name: 'Alice',
  extra: 'removed',
});
// result: { name: 'Alice' }
Signature:
strip(): ZodObject<Shape, ZodStrip>

Object Variants

z.strictObject()

Create a strict object schema that rejects unrecognized keys.
const schema = z.strictObject({
  id: z.string(),
  name: z.string(),
});

// Equivalent to:
const schema = z.object({ id: z.string(), name: z.string() }).strict();

z.looseObject()

Create a loose object schema that allows unrecognized keys.
const schema = z.looseObject({
  id: z.string(),
});

// Equivalent to:
const schema = z.object({ id: z.string() }).loose();

Type Inference

const UserSchema = z.object({
  id: z.string(),
  name: z.string(),
  email: z.string().email(),
  age: z.number().optional(),
  tags: z.array(z.string()),
});

type User = z.infer<typeof UserSchema>;
/*
{
  id: string;
  name: string;
  email: string;
  age?: number;
  tags: string[];
}
*/

type UserInput = z.input<typeof UserSchema>;
// Same as output for object schemas without transformations

Build docs developers (and LLMs) love