Thanks to visit codestin.com
Credit goes to github.com

Skip to content

fix(plugin-zod): wrap nullable allOf members instead of intersecting them#3665

Merged
stijnvanhulle merged 2 commits into
v4from
claude/hopeful-keller-0ixsoh-v4
Jun 23, 2026
Merged

fix(plugin-zod): wrap nullable allOf members instead of intersecting them#3665
stijnvanhulle merged 2 commits into
v4from
claude/hopeful-keller-0ixsoh-v4

Conversation

@stijnvanhulle

Copy link
Copy Markdown
Collaborator

What

Fixes #3661 (v4).

A nullable schema inside an allOf produced invalid Zod output:

export const getHealth200Schema = z.lazy(() => nullableStringSchema).and(.nullable())

The .and(.nullable()) is a syntax error.

Why

When a single nullable allOf member is merged into the intersection, its nullable keyword ends up as a sibling of the real members. The and handler in parser.ts only filtered out optional and describe, so nullable (and nullish/default) were parsed as intersection members — producing the broken .and(.nullable()).

How

Modifier keywords (nullable, nullish, optional, default, describe) are now separated from the intersection members. The real members build the .and() chain and the modifiers wrap the whole result:

// single nullable member
export const nullableAllOf = z.lazy(() => nullableString).nullable()

// multi-member allOf with a nullable member
export const nullableAllOfMulti = z.lazy(() => base).and(z.lazy(() => nullableString)).nullable()

Mini mode wraps the result with the functional modifiers (z.nullable(...)).

Tests

  • New regression test packages/plugin-zod/src/generators/nullableAllOf.test.tsx covering single/multi-member allOf and mini mode.
  • Full @kubb/plugin-zod suite (198) and the 3.0.x e2e suite (9) pass; no snapshot churn.

Note: v5 (main) already flattens single-member allOf and propagates nullable in @kubb/adapter-oas, so it emits valid output. A regression test for v5 is added separately in kubb-labs/plugins.

🤖 Generated with Claude Code


Generated by Claude Code

…them

A nullable schema inside an `allOf` had its `nullable` keyword merged in as a
sibling of the intersection members. The `and` handler treated it as a member,
emitting invalid output like `z.lazy(() => nullableStringSchema).and(.nullable())`.

Modifier keywords (`nullable`, `nullish`, `optional`, `default`, `describe`) are
now lifted out of the `.and()` chain and wrap the whole schema instead, producing
`z.lazy(() => nullableStringSchema).nullable()`. Mini mode wraps the result with
the functional modifiers.

Fixes #3661

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01WUhMV6aMGjVezMYmfzEyQs
@dosubot dosubot Bot added @kubb/plugin-zod bug Something isn't working typescript labels Jun 23, 2026
@changeset-bot

changeset-bot Bot commented Jun 23, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 36c91ed

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 22 packages
Name Type
@kubb/plugin-zod Patch
@kubb/plugin-client Patch
@kubb/plugin-mcp Patch
@kubb/plugin-react-query Patch
@kubb/plugin-solid-query Patch
@kubb/plugin-svelte-query Patch
@kubb/plugin-swr Patch
@kubb/plugin-vue-query Patch
@kubb/adapter-oas Patch
@kubb/ast Patch
@kubb/cli Patch
@kubb/core Patch
@kubb/mcp Patch
@kubb/oas Patch
@kubb/plugin-cypress Patch
@kubb/plugin-faker Patch
@kubb/plugin-msw Patch
@kubb/plugin-oas Patch
@kubb/plugin-redoc Patch
@kubb/plugin-ts Patch
kubb Patch
unplugin-kubb Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Jun 23, 2026

Copy link
Copy Markdown
More templates

@kubb/adapter-oas

npm i https://pkg.pr.new/@kubb/adapter-oas@3665

@kubb/ast

npm i https://pkg.pr.new/@kubb/ast@3665

@kubb/cli

npm i https://pkg.pr.new/@kubb/cli@3665

@kubb/core

npm i https://pkg.pr.new/@kubb/core@3665

kubb

npm i https://pkg.pr.new/kubb@3665

@kubb/mcp

npm i https://pkg.pr.new/@kubb/mcp@3665

@kubb/oas

npm i https://pkg.pr.new/@kubb/oas@3665

@kubb/plugin-client

npm i https://pkg.pr.new/@kubb/plugin-client@3665

@kubb/plugin-cypress

npm i https://pkg.pr.new/@kubb/plugin-cypress@3665

@kubb/plugin-faker

npm i https://pkg.pr.new/@kubb/plugin-faker@3665

@kubb/plugin-mcp

npm i https://pkg.pr.new/@kubb/plugin-mcp@3665

@kubb/plugin-msw

npm i https://pkg.pr.new/@kubb/plugin-msw@3665

@kubb/plugin-oas

npm i https://pkg.pr.new/@kubb/plugin-oas@3665

@kubb/plugin-react-query

npm i https://pkg.pr.new/@kubb/plugin-react-query@3665

@kubb/plugin-redoc

npm i https://pkg.pr.new/@kubb/plugin-redoc@3665

@kubb/plugin-solid-query

npm i https://pkg.pr.new/@kubb/plugin-solid-query@3665

@kubb/plugin-svelte-query

npm i https://pkg.pr.new/@kubb/plugin-svelte-query@3665

@kubb/plugin-swr

npm i https://pkg.pr.new/@kubb/plugin-swr@3665

@kubb/plugin-ts

npm i https://pkg.pr.new/@kubb/plugin-ts@3665

@kubb/plugin-vue-query

npm i https://pkg.pr.new/@kubb/plugin-vue-query@3665

@kubb/plugin-zod

npm i https://pkg.pr.new/@kubb/plugin-zod@3665

unplugin-kubb

npm i https://pkg.pr.new/unplugin-kubb@3665

commit: 36c91ed

@stijnvanhulle stijnvanhulle merged commit 08fc3cc into v4 Jun 23, 2026
14 checks passed
@stijnvanhulle stijnvanhulle deleted the claude/hopeful-keller-0ixsoh-v4 branch June 23, 2026 14:05
@github-actions github-actions Bot mentioned this pull request Jun 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants