Skip to content

fix(form-core): exclude undefined from FormState errors type#2066

Merged
crutchcorn merged 4 commits into
TanStack:mainfrom
isaackaara:fix/form-errors-type-exclude-undefined
May 10, 2026
Merged

fix(form-core): exclude undefined from FormState errors type#2066
crutchcorn merged 4 commits into
TanStack:mainfrom
isaackaara:fix/form-errors-type-exclude-undefined

Conversation

@isaackaara
Copy link
Copy Markdown
Contributor

@isaackaara isaackaara commented Mar 6, 2026

The runtime code in FormApi.ts explicitly filters out undefined values from the error map when building the errors array:

fieldErrors = Object.values(currBaseMeta.errorMap ?? {}).filter(
  (val) => val !== undefined,
) as never

But the type definition allows undefined in the union, forcing consumers to add unnecessary undefined checks:

// Before: TypeScript thinks errors can contain undefined
errors.forEach(error => {
  console.log(error.length)  // TS error: Object is possibly 'undefined'
})

This wraps the error union types with NonNullable<> in both the FormState.errors type and the getAllErrors() return type, aligning the types with the runtime behavior.

// After: undefined is excluded from the type, matching runtime
errors.forEach(error => {
  console.log(error.length)  // Works
})

Fixes #2022

Summary by CodeRabbit

  • Refactor
    • Tightened TypeScript typings for form error arrays to exclude null/undefined, improving compile-time safety and clearer error shapes.
    • Updated type-level tests to reflect the stricter error array element types.

Review Change Stack

The runtime code filters out undefined values from the errorMap when
building the errors array (via .filter(val => val !== undefined)),
but the type definition allowed undefined in the union. This forced
consumers to add unnecessary runtime undefined checks when iterating
over errors.

Wrapping the error union with NonNullable aligns the type with the
actual runtime behavior.

Fixes TanStack#2022
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Mar 6, 2026

⚠️ No Changeset found

Latest commit: a8f268c

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

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

Copy link
Copy Markdown
Member

@crutchcorn crutchcorn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes sense, thanks

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 10, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: efbc88ac-6a37-4cbb-8ed4-6f161aa6e5fd

📥 Commits

Reviewing files that changed from the base of the PR and between 433005e and 3be9ee8.

📒 Files selected for processing (4)
  • packages/form-core/src/FormApi.ts
  • packages/form-core/tests/FieldApi.test-d.ts
  • packages/form-core/tests/FormApi.test-d.ts
  • packages/form-core/tests/formOptions.test-d.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/form-core/src/FormApi.ts

📝 Walkthrough

Walkthrough

This PR tightens TypeScript type definitions for form error arrays by wrapping error element unions with NonNullable<...> in two locations: DerivedFormState.errors and FormApi.getAllErrors() return type. The changes reflect existing runtime filtering of undefined values, closing a type-definition mismatch.

Changes

Error Type Nullability

Layer / File(s) Summary
Form Error Type Definitions
packages/form-core/src/FormApi.ts
DerivedFormState.errors and FormApi.getAllErrors() return type's form.errors now wrap their error element unions in NonNullable<...>, excluding null/undefined from the type contract to match runtime filtering behavior.
Type-level Tests
packages/form-core/tests/FieldApi.test-d.ts, packages/form-core/tests/FormApi.test-d.ts, packages/form-core/tests/formOptions.test-d.ts
Type assertions updated to expect error arrays without undefined in element unions (e.g., '123'[], 'Too short!'[], `('Too short!'

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 With whiskers twitched and eyes alight,
We wrap the errors tight and right—
No nulls shall pass our type's defense,
Where runtime and the types now dance!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: wrapping error types with NonNullable to exclude undefined from the FormState errors type, directly matching the PR's core objective.
Description check ✅ Passed The description clearly explains the type mismatch, provides before/after code examples, identifies the runtime filtering behavior, and references the fixed issue, meeting all template requirements.
Linked Issues check ✅ Passed The PR fully addresses issue #2022 by wrapping error union types with NonNullable<> in both FormState.errors and getAllErrors() return type, removing undefined from compile-time types to match runtime behavior.
Out of Scope Changes check ✅ Passed All changes are scoped to the linked issue: three test files were updated to reflect the narrowed type expectations, and the FormApi.ts type definitions were modified to exclude undefined as required.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@nx-cloud
Copy link
Copy Markdown

nx-cloud Bot commented May 10, 2026

View your CI Pipeline Execution ↗ for commit 433005e

Command Status Duration Result
nx affected --targets=test:sherif,test:knip,tes... ✅ Succeeded 2m 39s View ↗
nx run-many --target=build --exclude=examples/** ✅ Succeeded 36s View ↗

☁️ Nx Cloud last updated this comment at 2026-05-10 19:15:22 UTC

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 10, 2026

More templates

@tanstack/angular-form

npm i https://pkg.pr.new/@tanstack/angular-form@2066

@tanstack/form-core

npm i https://pkg.pr.new/@tanstack/form-core@2066

@tanstack/form-devtools

npm i https://pkg.pr.new/@tanstack/form-devtools@2066

@tanstack/lit-form

npm i https://pkg.pr.new/@tanstack/lit-form@2066

@tanstack/preact-form

npm i https://pkg.pr.new/@tanstack/preact-form@2066

@tanstack/react-form

npm i https://pkg.pr.new/@tanstack/react-form@2066

@tanstack/react-form-devtools

npm i https://pkg.pr.new/@tanstack/react-form-devtools@2066

@tanstack/react-form-nextjs

npm i https://pkg.pr.new/@tanstack/react-form-nextjs@2066

@tanstack/react-form-remix

npm i https://pkg.pr.new/@tanstack/react-form-remix@2066

@tanstack/react-form-start

npm i https://pkg.pr.new/@tanstack/react-form-start@2066

@tanstack/solid-form

npm i https://pkg.pr.new/@tanstack/solid-form@2066

@tanstack/solid-form-devtools

npm i https://pkg.pr.new/@tanstack/solid-form-devtools@2066

@tanstack/svelte-form

npm i https://pkg.pr.new/@tanstack/svelte-form@2066

@tanstack/vue-form

npm i https://pkg.pr.new/@tanstack/vue-form@2066

commit: 3be9ee8

@crutchcorn crutchcorn merged commit 43123f9 into TanStack:main May 10, 2026
7 checks passed
@sentry
Copy link
Copy Markdown

sentry Bot commented May 10, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.71%. Comparing base (6892ed0) to head (3be9ee8).
⚠️ Report is 195 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2066      +/-   ##
==========================================
+ Coverage   90.35%   90.71%   +0.36%     
==========================================
  Files          38       59      +21     
  Lines        1752     2198     +446     
  Branches      444      550     +106     
==========================================
+ Hits         1583     1994     +411     
- Misses        149      183      +34     
- Partials       20       21       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug Report: Type mismatch in errors field - runtime filtering of undefined not reflected in type definition

2 participants