feat(zod): add useBrandedTypes option to append .brand() to generated schemas#3161
Conversation
… schemas (orval-labs#3160) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (4)
✅ Files skipped from review due to trivial changes (3)
📝 WalkthroughWalkthroughAdds a Changes
Sequence Diagram(s)sequenceDiagram
participant Config
participant Normalizer
participant Generator
participant FileSystem
rect rgba(200,230,201,0.5)
Config->>Normalizer: load output.override.zod (useBrandedTypes?)
end
rect rgba(187,222,251,0.5)
Normalizer->>Generator: provide normalized zod options (useBrandedTypes boolean)
end
rect rgba(255,224,178,0.5)
Generator->>FileSystem: emit schema files (append .brand(...) when useBrandedTypes=true)
FileSystem-->>Generator: write success
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~30 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
Adds an opt-in Zod output feature to generate nominally-typed schemas by appending Zod’s .brand() to generated schema exports (v3 generic form vs v4 runtime-arg form), plus tests and docs.
Changes:
- Introduces
override.zod.useBrandedTypesin core option types and normalizes it tofalseby default. - Appends
.brand()to generated route-level Zod schema exports, with v3/v4 syntax handling. - Adds unit + integration test coverage and documents the new option.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/configs/zod.config.ts | Adds an integration test config entry enabling useBrandedTypes. |
| tests/snapshots/zod/branded-types/branded-types.ts | New snapshot showing branded Zod schema exports. |
| packages/zod/src/zod.test.ts | Adds unit tests covering branded output across v3/v4, arrays, strict, and per-status responses. |
| packages/zod/src/index.ts | Implements .brand() appending during Zod route schema export assembly. |
| packages/orval/src/utils/options.ts | Normalizes useBrandedTypes with default false (global + per-op/tag overrides). |
| packages/core/src/types.ts | Adds useBrandedTypes to ZodOptions and NormalizedZodOptions. |
| packages/core/src/test-utils/context.ts | Updates test context defaults to include useBrandedTypes: false. |
| docs/content/docs/reference/configuration/output.mdx | Documents the new useBrandedTypes option and adds it to the example. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/zod/src/zod.test.ts`:
- Around line 6543-6545: The regex used in the assertion for
result.implementation has an extra `\)` which can cause false negatives when
matching branded item schemas; update the pattern in the expect call (the line
referencing result.implementation) to remove the extra paren and allow optional
whitespace before the `.brand`, e.g. change the regex to match /TestResponseItem
= zod\.object\([^)]*\)\s*\.brand/ so branded schemas are reliably detected.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 49f0a1d3-b564-449a-bb42-07d8bb34c3fc
📒 Files selected for processing (8)
docs/content/docs/reference/configuration/output.mdxpackages/core/src/test-utils/context.tspackages/core/src/types.tspackages/orval/src/utils/options.tspackages/zod/src/index.tspackages/zod/src/zod.test.tstests/__snapshots__/zod/branded-types/branded-types.tstests/configs/zod.config.ts
- Fix regex false negative in array response item brand assertion - Document that *Item helper schemas are intentionally not branded Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Closes #3160
Description
Add a new
override.zod.useBrandedTypesoption. When enabled, every generated Zod schema gets a.brand()call appended, using the export variable name as the brand identifier.Problem
Orval generates structurally typed Zod schemas. Two schemas with the same shape are fully interchangeable in TypeScript, so there is no compile-time error when you accidentally pass one where the other is expected. For example, a
UserResponseandOrganizationResponsewith identical fields can be silently swapped.Solution
With
useBrandedTypes: true, Orval appends.brand()to every generated Zod schema. This brings nominal type safety with zero runtime cost — Zod's.brand()is compile-time only.Generated output (Zod v3):
Generated output (Zod v4):
Changes
useBrandedTypes?: booleantoZodOptions/NormalizedZodOptionsinpackages/core/src/types.tsfalsein config normalization (packages/orval/src/utils/options.ts).brand()ingenerateZodRouteexport assembly (packages/zod/src/index.ts)useBrandedTypes: falseto test context defaults (packages/core/src/test-utils/context.ts)generateEachHttpStatus, partial generation (packages/zod/src/zod.test.ts)tests/configs/zod.config.ts,tests/__snapshots__/zod/branded-types/)docs/content/docs/reference/configuration/output.mdx)Note
This is different from #1222 / #2432 which focus on TypeScript type-level branded types (
type X = string & { __brand }). This PR is specifically about Zod schema-level.brand()in theclient: 'zod'output — a different code path.Summary by CodeRabbit
New Features
useBrandedTypesoption for Zod generation (default: false); enables optional branding on generated schemas and propagates into normalized and per-operation settings.Documentation
override.zod.useBrandedTypesand updated examples to show branded-schema behavior, including array-wrapper handling.Tests
Chores