# How to Use Zod's pick and omit for Partial Object Types: A Complete Guide

> Master Zod pick and omit to create partial object types. Select or exclude keys from Zod schemas for precise data shaping and type safety in your JavaScript projects.

- Repository: [Colin McDonnell/zod](https://github.com/colinhacks/zod)
- Tags: how-to-guide
- Published: 2026-02-23

---

**Zod's `pick` and `omit` methods let you derive new object schemas by selecting specific keys or excluding unwanted ones, returning immutable `ZodObject` instances that preserve type safety.**

When building TypeScript applications with the `colinhacks/zod` library, you frequently need to create variations of existing object schemas for different API endpoints or form validations. The `pick` and `omit` utilities provide a type-safe way to construct partial object types by surgically modifying a base schema's shape without mutating the original definition.

## Understanding Zod pick and omit

Zod implements `pick` and `omit` as core utilities that operate on `ZodObject` schemas. Both methods accept a **mask object** where truthy values indicate which keys to select or remove.

### The pick Method

The `pick` method creates a new schema containing **only** the keys specified in the mask. According to the source code in [`packages/zod/src/v4/core/util.ts`](https://github.com/colinhacks/zod/blob/main/packages/zod/src/v4/core/util.ts) (lines 593-620), the implementation follows four strict steps:

1. **Validate mask keys** – Each key in the mask must exist on the source schema; otherwise Zod throws an "Unrecognized key" error.
2. **Filter shape** – Only keys with truthy mask values are copied into a new shape object.
3. **Cache result** – The new shape is stored via `assignProp(this, "shape", newShape)` for future accesses.
4. **Clone schema** – Returns a shallow clone using `clone(schema, def)` without altering the original.

### The omit Method

Conversely, `omit` builds a new schema containing **all keys except** those marked truthy in the mask. Found in [`packages/zod/src/v4/core/util.ts`](https://github.com/colinhacks/zod/blob/main/packages/zod/src/v4/core/util.ts) (lines 622-649), this method mirrors `pick` but copies the full shape first, then deletes each masked key before caching and cloning.

## API Styles: Instance Methods vs Static Helpers

Zod exposes these utilities through two equivalent APIs:

**Instance methods** – Called directly on any `ZodObject`:

```typescript
const UserPreview = User.pick({ name: true, email: true });
const UserPublic = User.omit({ password: true, ssn: true });

```

**Static helpers** – Convenience wrappers located in [`packages/zod/src/v4/mini/schemas.ts`](https://github.com/colinhacks/zod/blob/main/packages/zod/src/v4/mini/schemas.ts) (lines 911-925 for `pick`, lines 918-925 for `omit`):

```typescript
const UserPreview = z.pick(User, { name: true });
const UserPublic = z.omit(User, { password: true });

```

Both approaches delegate to the same core implementation in [`util.ts`](https://github.com/colinhacks/zod/blob/main/util.ts) and produce identical results.

## Core Implementation and Safety Guardrails

### Refinement Validation

Before processing any keys, both methods check the source schema's refinement list (`currDef.checks`). If any refinements exist, Zod throws immediately:

```typescript
if (hasChecks) {
  throw new Error(".pick() cannot be used on object schemas containing refinements");
}

```

This guardrail prevents shape-changing operations from breaking custom validation logic attached to the original schema.

### Immutability Guarantees

The implementation ensures the original schema remains untouched by:
- Creating a new shape object rather than mutating the existing one
- Using `clone(schema, def)` to produce the returned schema
- Preserving all non-shape properties (descriptions, error maps, etc.) on the new instance

## Practical Code Examples

```typescript
import { z } from "zod";

/* ── Base schema ────────────────────────────────────────────── */
const User = z.object({
  id: z.string(),
  name: z.string(),
  email: z.string().email(),
  age: z.number().optional(),
  password: z.string().min(8),
});

/* ── pick – keep only the listed keys ──────────────────────── */
const UserPreview = User.pick({ name: true, email: true });
/* Type inferred as: { name: string; email: string } */

UserPreview.parse({ name: "Alice", email: "alice@example.com" }); // ✅
// UserPreview.parse({ id: "1" }); // ❌ runtime error – unknown key

/* ── omit – drop sensitive fields ─────────────────────────────── */
const UserPublic = User.omit({ password: true, id: true });
/* Type inferred as: { name: string; email: string; age?: number } */

UserPublic.parse({ name: "Bob", email: "bob@example.com" }); // ✅
// UserPublic.parse({ password: "secret123" }); // ❌ runtime error – `password` removed

/* ── Combining with partial for update schemas ───────────────── */
const UserUpdate = User.pick({ name: true, email: true, age: true }).partial();
/* Type: { name?: string; email?: string; age?: number } */

```

## Summary

- **Immutability**: Both `pick` and `omit` return new `ZodObject` instances without modifying the source schema.
- **Safety checks**: Schemas containing refinements cannot use these methods to prevent validation logic corruption.
- **Dual API**: Use either instance methods (`schema.pick()`) or static helpers (`z.pick()`) based on your coding style.
- **Type inference**: TypeScript automatically narrows the output type to match the selected or remaining keys.
- **Test coverage**: Reference implementations are validated in [`packages/zod/src/v4/classic/tests/pickomit.test.ts`](https://github.com/colinhacks/zod/blob/main/packages/zod/src/v4/classic/tests/pickomit.test.ts) and [`packages/zod/src/v4/mini/tests/object.test.ts`](https://github.com/colinhacks/zod/blob/main/packages/zod/src/v4/mini/tests/object.test.ts).

## Frequently Asked Questions

### Can I use pick and omit on schemas that have refinements?

No. According to the source code in [`packages/zod/src/v4/core/util.ts`](https://github.com/colinhacks/zod/blob/main/packages/zod/src/v4/core/util.ts), both methods check for the presence of refinements (`hasChecks`) and throw a runtime error if any exist. This prevents you from accidentally breaking custom validation logic that depends on the original object shape.

### Do pick and omit modify the original schema object?

No. Zod treats these operations as immutable transformations. The methods create a new shape object, cache it on a cloned schema instance via `clone(schema, def)`, and return the clone while leaving the original schema untouched.

### What is the difference between the instance method and static helper versions?

There is no functional difference. The static helpers `z.pick(schema, mask)` and `z.omit(schema, mask)` defined in [`packages/zod/src/v4/mini/schemas.ts`](https://github.com/colinhacks/zod/blob/main/packages/zod/src/v4/mini/schemas.ts) are thin wrappers that forward arguments to the instance methods. Choose based on readability—use static helpers when you want to treat the operation as a functional transformation, and instance methods for fluent chaining.

### Can I chain pick or omit with other Zod methods like partial or required?

Yes. Because `pick` and `omit` return full `ZodObject` instances, you can chain them with any other object method. For example, `User.pick({ name: true, email: true }).partial()` creates a schema where both `name` and `email` are optional, which is useful for PATCH request validation in REST APIs.