Skip to content

fix: remove errant Field.Field usage and useForm().useField()#2149

Merged
crutchcorn merged 13 commits intomainfrom
remove-dupe-field
May 8, 2026
Merged

fix: remove errant Field.Field usage and useForm().useField()#2149
crutchcorn merged 13 commits intomainfrom
remove-dupe-field

Conversation

@crutchcorn
Copy link
Copy Markdown
Member

@crutchcorn crutchcorn commented May 6, 2026

This PR removes the ability to do:

<form.Field children={field => <field.Field/>}/>

And:

const {useField} = useForm();

Which I think was errantly added, as I can't think of any reliable reason why we'd want to support this.

Summary by CodeRabbit

  • Breaking Changes

    • Field hook no longer exposes a Field sub-component on its return value — update code that accessed Field via the hook.
    • Form API no longer provides a useField helper on the extended surface; only Field component and other helpers remain.
    • Several exported type aliases and the augmented field API were removed — update affected type usages.
    • Svelte form API now exposes Field as a component-style member instead of the previous factory-style helper.
  • Chores

    • ESLint configs updated to disable the no-use-context rule for TS/TSX.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 6, 2026

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 687abb19-4959-4483-868a-e9eba9a8e39a

📥 Commits

Reviewing files that changed from the base of the PR and between 804bc53 and 45474c8.

📒 Files selected for processing (6)
  • packages/react-form-devtools/eslint.config.js
  • packages/react-form-nextjs/eslint.config.js
  • packages/react-form-remix/eslint.config.js
  • packages/react-form-start/eslint.config.js
  • packages/react-form/eslint.config.js
  • packages/react-form/src/createFormHook.tsx
💤 Files with no reviewable changes (1)
  • packages/react-form/src/createFormHook.tsx
✅ Files skipped from review due to trivial changes (3)
  • packages/react-form/eslint.config.js
  • packages/react-form-remix/eslint.config.js
  • packages/react-form-start/eslint.config.js

📝 Walkthrough

Walkthrough

The PR removes Field sub-component augmentation from useField across frameworks, updates type/imports, simplifies useField to return FieldApi directly, switches Svelte createForm to expose a Field component constructor, and adjusts Vue useForm wiring to drop extendedApi.useField.

Changes

useField Hook API Simplification (React + Vue + Svelte + Solid)

Layer / File(s) Summary
Type & Import Updates
packages/react-form/src/useField.tsx, packages/vue-form/src/useField.tsx, packages/svelte-form/src/Field.svelte, packages/svelte-form/src/createFormCreator.svelte.ts, packages/svelte-form/src/index.ts, packages/svelte-form/src/types.ts
Removed unused imports and deprecated augmentation types (useRef, ReactElement, SvelteFieldApi, CreateField, UseField alias); added/adjusted type-only imports (FunctionComponent/ReactNode, UseFieldOptions/UseFieldOptionsBound, FieldComponent/WithoutFunction, Svelte Component/Snippet).
Core Implementation
packages/react-form/src/useField.tsx, packages/vue-form/src/useField.tsx
useField now returns the raw FieldApi instance; removed extendedApi creation and the explicit extendedApi.Field = Field assignment; Vue removed exported UseField type alias.
Svelte Field & createForm
packages/svelte-form/src/Field.svelte, packages/svelte-form/src/createForm.svelte.ts
Simplified extendedApi typing and removed extendedApi.Field attachment in Field.svelte; createForm now exposes extendedApi.Field as a constructor-style call Field(internal, props) injecting the current form API; SvelteFormApi.Field typing updated to FieldComponent<...>.
Form Wiring / API Surface (Vue)
packages/vue-form/src/useForm.tsx
Stopped importing useField; import Field and type-only FieldComponent; removed VueFormApi.useField from the interface and deleted runtime extendedApi.useField while keeping extendedApi.Field, useStore, and Subscribe.
Solid createForm / createField
packages/solid-form/src/createField.tsx, packages/solid-form/src/createForm.tsx
Simplified extendedApi typing in createField; removed createField factory from createForm; createForm exposes extendedApi.Field wrapper that renders Field with form={api} and uses FieldComponent typing in SolidFormApi.
React createFormHook
packages/react-form/src/createFormHook.tsx
Removed an inline eslint-disable comment that preceded fieldContext.Provider in AppField render; runtime provider usage unchanged.
ESLint Configs
packages/react-form-devtools/eslint.config.js, packages/react-form-nextjs/eslint.config.js, packages/react-form-remix/eslint.config.js, packages/react-form-start/eslint.config.js, packages/react-form/eslint.config.js
Added explicit overrides to disable @eslint-react/no-use-context for TypeScript/TSX files in multiple package ESLint configs.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 Tip-tap, I hop through code tonight,
I tuck the Field away from public sight,
Types trimmed neat, imports in a row,
Hooks return simply what callers should know,
A little hop, and the API’s light. 🥕

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The PR description clearly explains what is being removed and why, but is missing required checklist items and changeset generation confirmation from the template. Complete the checklist items and confirm whether a changeset was generated, as this appears to be a published code change affecting the public API.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title concisely summarizes the main changes: removing nested Field usage and useForm().useField() patterns. It is specific, clear, and directly relates to the primary objective of the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch remove-dupe-field

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 6, 2026

View your CI Pipeline Execution ↗ for commit 2e14fe3

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

☁️ Nx Cloud last updated this comment at 2026-05-08 13:35:43 UTC

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 6, 2026

🚀 Changeset Version Preview

No changeset entries found. Merging this PR will not cause a version bump for any packages.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 6, 2026

More templates

@tanstack/angular-form

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

@tanstack/form-core

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

@tanstack/form-devtools

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

@tanstack/lit-form

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

@tanstack/react-form

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

@tanstack/react-form-devtools

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

@tanstack/react-form-nextjs

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

@tanstack/react-form-remix

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

@tanstack/react-form-start

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

@tanstack/solid-form

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

@tanstack/solid-form-devtools

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

@tanstack/svelte-form

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

@tanstack/vue-form

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

commit: 45474c8

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/react-form/src/useField.tsx`:
- Line 275: The PR removed the ReactFieldApi augmentation and the
extendedApi.Field assignment which breaks consumers using field.Field (e.g., in
<form.Field>{(field) => <field.Field .../>}</form.Field>); update the release
notes and migration guide and ensure the commit includes a Conventional Commits
breaking change marker (either use fix!: or add a BREAKING CHANGE: footer) that
explains the removal, cites the affected symbols (ReactFieldApi,
extendedApi.Field, field.Field), and documents the recommended replacements (use
the outer form.Field or call useField directly) with a short example and any
migration steps.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 25919c7d-28c0-465a-abc8-bcd99ea17f73

📥 Commits

Reviewing files that changed from the base of the PR and between 93be6f0 and 426097e.

📒 Files selected for processing (1)
  • packages/react-form/src/useField.tsx

Comment thread packages/react-form/src/useField.tsx
@sentry
Copy link
Copy Markdown

sentry Bot commented May 6, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 73.66%. Comparing base (6892ed0) to head (45474c8).
⚠️ Report is 174 commits behind head on main.

Additional details and impacted files
@@             Coverage Diff             @@
##             main    #2149       +/-   ##
===========================================
- Coverage   90.35%   73.66%   -16.70%     
===========================================
  Files          38       32        -6     
  Lines        1752      467     -1285     
  Branches      444       61      -383     
===========================================
- Hits         1583      344     -1239     
+ Misses        149      107       -42     
+ Partials       20       16        -4     

☔ 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.

@crutchcorn crutchcorn force-pushed the remove-dupe-field branch from 426097e to 3097a2d Compare May 7, 2026 09:15
@crutchcorn crutchcorn force-pushed the remove-dupe-field branch from 3097a2d to 13bc04a Compare May 7, 2026 09:19
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (3)
packages/vue-form/src/useField.tsx (2)

246-254: 💤 Low value

The IIFE no longer serves any purpose — collapse it.

After removing the extendedApi augmentation, the IIFE simply instantiates and immediately returns a FieldApi. The wrapper can be dropped.

♻️ Proposed simplification
-  const fieldApi = (() => {
-    const api = new FieldApi({
-      ...opts,
-      form: opts.form,
-      name: opts.name,
-    })
-
-    return api
-  })()
+  const fieldApi = new FieldApi({
+    ...opts,
+    form: opts.form,
+    name: opts.name,
+  })
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/vue-form/src/useField.tsx` around lines 246 - 254, The IIFE around
fieldApi is now redundant—replace the self-invoking function with a direct
instantiation: create fieldApi by assigning new FieldApi({...opts, form:
opts.form, name: opts.name}) directly (remove the (()=>{...})() wrapper); ensure
you keep the same variable name fieldApi and use the same opts/Form/name
properties passed to the FieldApi constructor.

157-185: ⚡ Quick win

VueFieldApi is a misleading dead export that doesn't match the actual useField return value.

VueFieldApi declares Field: FieldComponent<...>, but useField returns { api: fieldApi, state: fieldState } where fieldApi is a bare FieldApi instance with no Field property. While the Field component is exported separately from the same file, it is never attached to the api object. Any code expecting api.Field based on the VueFieldApi type will silently fail at runtime.

Either remove VueFieldApi if it's not needed, or update the interface to reflect what useField actually provides.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/vue-form/src/useField.tsx` around lines 157 - 185, The VueFieldApi
type is incorrect: it claims a Field property (Field: FieldComponent<...>) but
useField actually returns { api: fieldApi, state: fieldState } where fieldApi is
a bare FieldApi instance and Field is exported separately; update VueFieldApi to
match the actual return shape (e.g., export interface VueFieldApi<...> { api:
FieldApi<...>; state: FieldState<...>; } using the existing FieldApi and
FieldState types) or remove the VueFieldApi export entirely if it's unused so
consumers don't expect api.Field at runtime; adjust any related exports or
usages to the corrected type name (VueFieldApi) or the real Field component as
needed.
packages/vue-form/src/useForm.tsx (1)

4-4: 💤 Low value

Merge the two './useField' imports into one.

Lines 4 and 20 both import from './useField'; they can be combined using the inline type modifier.

♻️ Proposed consolidation
-import { Field } from './useField'
 ...
-import type { FieldComponent } from './useField'
+import { Field, type FieldComponent } from './useField'

Also applies to: 20-20

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/vue-form/src/useForm.tsx` at line 4, Two separate imports from
'./useField' should be merged into a single import statement; locate both import
lines (the one importing Field and the other import at line 20) and consolidate
them into one import from './useField', using the inline type modifier for
type-only imports (e.g., import type { Field } along with any value exports) so
that type/value imports are correctly distinguished and no duplicate module
specifiers remain.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/vue-form/src/useField.tsx`:
- Around line 246-254: The IIFE around fieldApi is now redundant—replace the
self-invoking function with a direct instantiation: create fieldApi by assigning
new FieldApi({...opts, form: opts.form, name: opts.name}) directly (remove the
(()=>{...})() wrapper); ensure you keep the same variable name fieldApi and use
the same opts/Form/name properties passed to the FieldApi constructor.
- Around line 157-185: The VueFieldApi type is incorrect: it claims a Field
property (Field: FieldComponent<...>) but useField actually returns { api:
fieldApi, state: fieldState } where fieldApi is a bare FieldApi instance and
Field is exported separately; update VueFieldApi to match the actual return
shape (e.g., export interface VueFieldApi<...> { api: FieldApi<...>; state:
FieldState<...>; } using the existing FieldApi and FieldState types) or remove
the VueFieldApi export entirely if it's unused so consumers don't expect
api.Field at runtime; adjust any related exports or usages to the corrected type
name (VueFieldApi) or the real Field component as needed.

In `@packages/vue-form/src/useForm.tsx`:
- Line 4: Two separate imports from './useField' should be merged into a single
import statement; locate both import lines (the one importing Field and the
other import at line 20) and consolidate them into one import from './useField',
using the inline type modifier for type-only imports (e.g., import type { Field
} along with any value exports) so that type/value imports are correctly
distinguished and no duplicate module specifiers remain.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a490d4dc-ecf7-46cd-8a50-2965084fbcd4

📥 Commits

Reviewing files that changed from the base of the PR and between 426097e and 3097a2d.

📒 Files selected for processing (3)
  • packages/react-form/src/useField.tsx
  • packages/vue-form/src/useField.tsx
  • packages/vue-form/src/useForm.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/react-form/src/useField.tsx

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/svelte-form/src/createForm.svelte.ts`:
- Line 4: The public API removed the createField method from SvelteFormApi (so
form.createField will be undefined for consumers); restore a compatibility
wrapper by adding a createField method back onto the object returned by
createForm (or the SvelteFormApi implementation) that delegates to the
standalone createField export, or re-export createField from the module so
existing form.createField calls still work; update the SvelteFormApi type to
include createField and ensure the method simply calls the imported createField
(preserving current behavior) while marking it as deprecated in comments.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6a910576-b7f3-47db-98fe-f90543fe5829

📥 Commits

Reviewing files that changed from the base of the PR and between 3097a2d and 13bc04a.

📒 Files selected for processing (5)
  • packages/svelte-form/src/Field.svelte
  • packages/svelte-form/src/createForm.svelte.ts
  • packages/svelte-form/src/createFormCreator.svelte.ts
  • packages/vue-form/src/useField.tsx
  • packages/vue-form/src/useForm.tsx
✅ Files skipped from review due to trivial changes (1)
  • packages/svelte-form/src/createFormCreator.svelte.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/vue-form/src/useForm.tsx
  • packages/vue-form/src/useField.tsx

Comment thread packages/svelte-form/src/createForm.svelte.ts
@crutchcorn
Copy link
Copy Markdown
Member Author

I'm very suspicious about removing these changes. Because we have so many of these instances in our code it makes me think that we added this purposefully at some point, but I can't fathom why.

@crutchcorn crutchcorn changed the title fix: remove errant Field.Field usage fix: remove errant Field.Field usage and useForm().useField() May 7, 2026
@crutchcorn crutchcorn force-pushed the remove-dupe-field branch from 13bc04a to 898223f Compare May 7, 2026 09:25
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/solid-form/src/createField.tsx`:
- Line 240: The return type advertises SolidFieldApi.Field but extendedApi
(created in createField and passed into makeFieldReactive) never gets a Field
property, so consumers see field().Field at compile-time but it's undefined at
runtime; fix by adding a proper Field implementation onto extendedApi before
passing it to makeFieldReactive (implement a FieldComponent matching
SolidFieldApi's Field signature and assign extendedApi.Field = <that
component>), or alternatively remove SolidFieldApi from the
createField/makeFieldReactive return type so the type matches runtime — update
the symbols extendedApi, createField, makeFieldReactive, and SolidFieldApi
accordingly to keep type and runtime consistent.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: a745f6a1-a5d9-4889-ae57-7705bb6914db

📥 Commits

Reviewing files that changed from the base of the PR and between 13bc04a and 804bc53.

📒 Files selected for processing (6)
  • packages/react-form/src/createFormHook.tsx
  • packages/solid-form/src/createField.tsx
  • packages/solid-form/src/createForm.tsx
  • packages/svelte-form/src/createForm.svelte.ts
  • packages/svelte-form/src/index.ts
  • packages/svelte-form/src/types.ts
💤 Files with no reviewable changes (1)
  • packages/svelte-form/src/types.ts
✅ Files skipped from review due to trivial changes (1)
  • packages/react-form/src/createFormHook.tsx

> = api as never

extendedApi.Field = Field as never
const extendedApi: typeof api = api as never
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify mismatch: runtime assignment removed, but type still includes SolidFieldApi in createField path.
rg -n -C3 "const extendedApi: typeof api = api as never|extendedApi\\.Field\\s*=|function makeFieldReactive|SolidFieldApi<" packages/solid-form/src/createField.tsx

Repository: TanStack/form

Length of output: 1119


🏁 Script executed:

# First, let's see the full SolidFieldApi interface definition
sed -n '23,52p' packages/solid-form/src/createField.tsx

Repository: TanStack/form

Length of output: 1112


🏁 Script executed:

# Now let's see the full context around line 240 and how extendedApi is used after
sed -n '235,280p' packages/solid-form/src/createField.tsx

Repository: TanStack/form

Length of output: 1033


🏁 Script executed:

# Check if extendedApi.Field is assigned anywhere in the file
rg -n "extendedApi\.Field\s*=" packages/solid-form/src/createField.tsx

Repository: TanStack/form

Length of output: 39


🏁 Script executed:

# Also check the return type and return statement of makeFieldReactive
sed -n '150,160p' packages/solid-form/src/createField.tsx

Repository: TanStack/form

Length of output: 258


🏁 Script executed:

# Get the complete return statement starting from line 250+
sed -n '260,300p' packages/solid-form/src/createField.tsx

Repository: TanStack/form

Length of output: 1054


🏁 Script executed:

# Check all uses of extendedApi in the file
rg -n "extendedApi" packages/solid-form/src/createField.tsx

Repository: TanStack/form

Length of output: 138


🏁 Script executed:

# Also, let's see the makeFieldReactive function's return statement
sed -n '155,180p' packages/solid-form/src/createField.tsx

Repository: TanStack/form

Length of output: 774


🏁 Script executed:

# Get the createField function signature with return type
sed -n '167,210p' packages/solid-form/src/createField.tsx

Repository: TanStack/form

Length of output: 1952


🏁 Script executed:

# Get the return type annotation of createField
sed -n '207,225p' packages/solid-form/src/createField.tsx

Repository: TanStack/form

Length of output: 439


🏁 Script executed:

# Get more of the function signature to find the return type
sed -n '220,240p' packages/solid-form/src/createField.tsx

Repository: TanStack/form

Length of output: 462


🏁 Script executed:

# Search for the return type annotation more precisely
rg -n "^\) " packages/solid-form/src/createField.tsx | head -5

Repository: TanStack/form

Length of output: 73


🏁 Script executed:

# Also check the full createField signature with better context
sed -n '174,236p' packages/solid-form/src/createField.tsx | grep -n "=>"

Repository: TanStack/form

Length of output: 94


🏁 Script executed:

# Get a cleaner view of the full createField function signature
awk '/^export function createField</,/^\) \{/' packages/solid-form/src/createField.tsx | tail -30

Repository: TanStack/form

Length of output: 694


🏁 Script executed:

# Check if Field property is ever added anywhere in the createField function
sed -n '238,290p' packages/solid-form/src/createField.tsx

Repository: TanStack/form

Length of output: 1183


Type contract advertises field().Field, but runtime never provides it.

createField passes extendedApi to makeFieldReactive without adding a Field property, yet the return type signature includes SolidFieldApi, which declares Field: FieldComponent<...>. This creates a compile-time-success / runtime-undefined trap: consumers can write field().Field and TypeScript accepts it, but the property is never defined at runtime.

The root cause is that extendedApi on line 240 is never enriched with the Field property before being passed to makeFieldReactive on line 288. Meanwhile, makeFieldReactive's return type contract (() => FieldApi<...> & SolidFieldApi<...>) still advertises Field via SolidFieldApi.

Either add the Field property to extendedApi before passing it to makeFieldReactive, or remove SolidFieldApi from the return type to match the actual runtime behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/solid-form/src/createField.tsx` at line 240, The return type
advertises SolidFieldApi.Field but extendedApi (created in createField and
passed into makeFieldReactive) never gets a Field property, so consumers see
field().Field at compile-time but it's undefined at runtime; fix by adding a
proper Field implementation onto extendedApi before passing it to
makeFieldReactive (implement a FieldComponent matching SolidFieldApi's Field
signature and assign extendedApi.Field = <that component>), or alternatively
remove SolidFieldApi from the createField/makeFieldReactive return type so the
type matches runtime — update the symbols extendedApi, createField,
makeFieldReactive, and SolidFieldApi accordingly to keep type and runtime
consistent.

Copy link
Copy Markdown
Contributor

@LeCarbonator LeCarbonator left a comment

Choose a reason for hiding this comment

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

Looks good! Resolve the note since it may affect React 17/18. Otherwise, feel free to merge anytime.

Comment thread packages/react-form/src/createFormHook.tsx Outdated
@crutchcorn crutchcorn merged commit dd68a7b into main May 8, 2026
8 of 9 checks passed
@crutchcorn crutchcorn deleted the remove-dupe-field branch May 8, 2026 14:15
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.

2 participants