Nominal identifiers
Prevent mixing values such as user IDs, order IDs, and currency amounts that share the same primitive representation.
Zod · Function
.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.
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.
schema.brand<T, D>();| Name | Type | Description |
|---|---|---|
T | string-like brand type | A compile-time label identifying the brand, such as "USD" or "Cat". |
D | "out" | "in" | "inout" | Optional direction selector: "out" (default), "in", or "inout". |
A schema with the same runtime parsing behavior and an inferred type carrying the requested brand.
.brand() augments the schema's inferred TypeScript type with a compile-time brand..brand<"Name">() call brands output inference rather than input inference.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.
Prevent mixing values such as user IDs, order IDs, and currency amounts that share the same primitive representation.
Require callers to pass values that have already passed a specific schema validation step.
Represent units or semantic categories over strings and numbers without changing their runtime representation.
.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.
.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().
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.inputz.output.parsez.stringz.objectz.$brand