fix(form-core): keep undefined out of the field error array type - #2383
fix(form-core): keep undefined out of the field error array type#2383CodeAndParty wants to merge 1 commit into
undefined out of the field error array type#2383Conversation
`FieldLikeMetaDerived['errors']` unions `UnwrapOneLevelOfArray<...>` over all nine validator slots. Every slot without a validator resolves to `undefined`, and `UnwrapOneLevelOfArray<undefined>` is `undefined`, so each unused slot leaked `undefined` into the element type. With a single form-level Standard Schema — eight slots unused — the array inferred as `(StandardSchemaV1Issue | undefined)[]`, which cannot be iterated without a guard or a cast. The value is already filtered at runtime, and the form-level `errors` types already wrap their union in `NonNullable`. Wrap the field-level union to match. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (10)
Included review availability: Your plan provides up to 8 included reviews per hour; 7 remain after this review. 📝 WalkthroughWalkthroughThe change narrows field and group error array element types by removing ChangesError type narrowing
Priority: ⬇️ Low Estimated code review effort: 2 (Simple) | ~10 minutes Change: Bug fix · Severity of issue fixed: Low Merge Risk: ⚪ Minimal · up to The change consistently narrows error-array element types without altering runtime validation behavior. No actionable merge risk remains. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 5 functions across 9 files. (1 skipped: 1 unsupported.)
✨ 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 |
🎯 Changes
field.state.meta.errorscarries a spuriousundefinedin its element type, so the array can't be iterated without a guard or a cast:Cause
FieldLikeMetaDerived['errors']unionsUnwrapOneLevelOfArray<UnwrapFieldValidateOrFn<…>>across all nine validator slots. A slot with no validator resolves toundefined, andUnwrapOneLevelOfArray<undefined>isundefined(T extends (infer U)[] ? U : T), so every unused slot contributesundefinedto the element union. A single form-level schema leaves eight slots unused.This is not specific to
onDynamicor to Standard Schema — any config that leaves slots empty is affected.Why
NonNullableis the right fixThe value is already filtered at runtime, in
FormApi:Group meta does the same (
if (curr === undefined) return acc). And the form-level types already wrap their unions inNonNullable—FormState['errors']andgetAllErrors()['form']['errors']both do.FieldLikeMetaDerived['errors']was the only one that didn't, which is why two adjacent tests with the identical validator disagreed:So this aligns the field-level type with both the runtime and the existing form-level convention.
Updated assertions
Five existing type tests encoded the old shape and are updated to drop
| undefined— this is the behavioural crux of the PR, so worth a close look:form-core/tests/FieldApi.test-d.ts(4 assertions)form-core/tests/FormGroupApi.test-d.ts, mirrored inreact-form,solid-form,preact-formTwo runtime tests had defensively written
key={err?.toString()}; the optional chain is now flagged as unnecessary by@typescript-eslint/no-unnecessary-conditionand has been removed — a nice confirmation that the fix reaches real call sites.Added coverage
Two regression tests in
form-core/tests/standardSchemaValidator.test-d.ts:Array<StandardSchemaV1Issue>, and.map((i) => i.message)isArray<string>'Required' | undefined→Array<StandardSchemaV1Issue | 'Required'>, confirming a validator's own return type is still preserved and only the spuriousundefinedis dropped✅ Checklist
pnpm test:pr.Verified across all 14 packages:
test:types(TS 5.4–5.9),test:lib,test:eslint, andbuildall pass.🚀 Release Impact
🤖 Generated with Claude Code
Summary by CodeRabbit
undefinedvalues.