fix(v4): prevent superRefine suppression on missing optional fields (#5653)#5658
fix(v4): prevent superRefine suppression on missing optional fields (#5653)#5658tushargr0ver wants to merge 1 commit intocolinhacks:mainfrom
Conversation
There was a problem hiding this comment.
Clean, minimal fix for a real regression. The approach of using a runtime-only "exactOptional" value while preserving the public type signature is pragmatic and avoids breaking changes. Tests pass and the logic is sound.
Approving with one minor observation (non-blocking): the handleCatchall function still uses optout === "optional" (line 1812), but this is actually fine because for catchall, we iterate over keys that are already present in the input, so the !(key in input) check in handlePropertyResult would always be false—errors are never suppressed for catchall regardless.
|
✅ Review complete Reviewed PR #5658 which fixes a regression where Summary: The fix correctly distinguishes |
Fixes #5653
Description
This PR fixes a regression in v4.3.0 where
superRefineerrors onoptional()fields were suppressed if the field was missing from the input object.The issue was caused by
ZodObjectsuppressing errors for missing keys ifoptoutwas "optional". This behavior is correct forexactOptional(where missing keys are valid but explicit undefined is not), but incorrect for standardoptionalfields which handleundefinedinternally (and should surface errors from refinements).Changes
ZodExactOptionalto useoptout="exactOptional"at runtime.ZodObject(standard and JIT) to only suppress errors ifoptout === "exactOptional".ZodUnionto correctly inferoptoutstatus.Notes
To avoid breaking public types and massive variance issues,
optoutremains typed as"optional" | undefinedin the interface, but we cast toanyinternally to assign/check"exactOptional".