Skip to content
masterclassBuddyTech Buzz5 fresh blogs · 5:00 AM IST

Zod · Function

z.brand

.brand() adds a compile-time marker to a Zod schema’s inferred type, separating validated values from ordinary structurally similar values. It is static-only and does not change parsed runtime values.

How it works

Call .brand() on a schema to attach a compile-time marker to its inferred type. Parsing is still required to obtain a branded value, while runtime parsing behavior remains unchanged; the default marker is applied to the output type.

Syntax

schema.brand<T, D>();

Parameters

NameTypeDescription
Tstring-like brand typeA compile-time label identifying the brand, such as "USD" or "Cat".
D"out" | "in" | "inout"Optional direction selector: "out" (default), "in", or "inout".

Returns

A schema with the same runtime parsing behavior and an inferred type carrying the requested brand.

Key points

  • .brand() augments the schema's inferred TypeScript type with a compile-time brand.
  • The marker provides nominal-style separation between validated values and ordinary values with the same apparent structure.
  • A normal .brand<"Name">() call brands output inference rather than input inference.
  • A second generic controls whether the marker applies to input, output, or both sides of the schema.
  • In current Zod, branding is represented through inferred-type modification rather than a separate public branded schema class.

Common mistakes

  • Branding changes TypeScript assignability only; it does not alter the value returned at runtime.
  • A plain value with the underlying shape is not automatically branded; obtain the branded type through schema parsing.
  • The optional direction generic is available only from Zod 4.2 onward.

Example: Brand a validated value

import * as z from "zod";

const USD = z.string().brand<"USD">();
type USD = z.output<typeof USD>;

function charge(amount: USD) {
  console.log(`Charging ${amount}`);
}

const amount = USD.parse("19.99");
charge(amount);

Parsing produces a value whose static type carries the USD brand, so it can be passed to functions requiring validated USD values.

When to use it

Nominal identifiers

Prevent mixing values such as user IDs, order IDs, and currency amounts that share the same primitive representation.

Validated domain values

Require callers to pass values that have already passed a specific schema validation step.

Domain-specific primitives

Represent units or semantic categories over strings and numbers without changing their runtime representation.

Interview questions

QWhat problem does .brand() solve?

.brand() adds a brand to the schema's inferred type, preventing plain structurally equivalent data from being assignable to that branded type. The brand is static and does not change the runtime result of parsing.

Follow-up: How do you get a value that satisfies the branded type? Parse input with the branded schema; a manually constructed unbranded value will not satisfy the branded type.

QWhich inferred type does .brand() affect by default?

By default, only the output type is branded. Thus z.output<typeof Schema> includes the brand, while z.input<typeof Schema> remains the underlying input type.

Follow-up: How can input branding be enabled? Pass a second generic direction such as "in" or "inout" to .brand().

QHow can the brand direction be customized?

The method accepts a brand name generic and can also accept a direction generic: "out" for output, "in" for input, or "inout" for both. The default direction is output branding.

Follow-up: What version constraint applies to direction selection? The documentation marks the two-generic form as requiring Zod 4.2 or newer.

  • z.input
  • z.output
  • .parse
  • z.string
  • z.object
  • z.$brand

Source: Defining schemas | Zod. Checked 2026-10-15.