Skip to content

feat: add ability to get form type from Svelte#2159

Open
crutchcorn wants to merge 1 commit intomainfrom
svelte-get-form-type
Open

feat: add ability to get form type from Svelte#2159
crutchcorn wants to merge 1 commit intomainfrom
svelte-get-form-type

Conversation

@crutchcorn
Copy link
Copy Markdown
Member

@crutchcorn crutchcorn commented May 8, 2026

This PR adds the ability to get the type of form to be passed via props:

Before

<script lang="ts">
  import type { createAppForm } from '../../runes/form.js'
  import { peopleFormOpts } from './shared-form.js'

  type AppForm = ReturnType<typeof createAppForm<typeof peopleFormOpts.defaultValues>>

  const { form }: { form: AppForm } = $props()
</script>

After

<script lang="ts">
  import { getFormType } from '../../runes/form.js'
  import { peopleFormOpts } from './shared-form.js'

  const formType = getFormType({ ...peopleFormOpts })

  const { form }: { form: typeof formType } = $props()
</script>

Summary by CodeRabbit

  • Documentation

    • Updated form composition guide introducing the getFormType helper for simplified, type-safe derivation of form props in child components, eliminating manual type construction patterns.
  • Refactor

    • Example Svelte components and form creator exports updated to demonstrate and use the new helper throughout the codebase.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 8, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

This PR introduces a getFormType helper function to the Svelte form library that provides a type-safe alternative to manual ReturnType aliases when typing child component form props. The helper is added to createFormCreator, exported through configuration, adopted by example components, and documented with comprehensive usage guidance.

Changes

getFormType Form Prop Typing

Layer / File(s) Summary
Core API Export
packages/svelte-form/src/createFormCreator.svelte.ts
New generic getFormType helper added to createFormCreator return object, accepts FormOptions and returns AppFieldExtendedSvelteFormApi for type derivation.
Runtime Configuration
examples/svelte/large-form/src/runes/form.ts
Form configuration module destructures and re-exports getFormType from createFormCreator alongside createAppForm.
Component Prop Typing
examples/svelte/large-form/src/features/people/address-fields.svelte, emergency-contact.svelte
Child components switch from manual AppForm type aliases to computing formType via getFormType({ ...peopleFormOpts }) and typing props as typeof formType.
Documentation
docs/framework/svelte/guides/form-composition.md
New "Getting the Form Type" section added with updated code examples in basic setup, tree-shaking variant, and comprehensive "put it all together" sections demonstrating getFormType usage.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 A helper hops to save the day,
getFormType shows the way,
No more aliases, long and raw,
Type your props with simpler awe! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description is incomplete. It only shows before/after code examples but lacks sections from the required template like checklist items and release impact information. Complete the description by adding the required sections: checklist items confirming testing and contribution guide adherence, and release impact section indicating whether a changeset was generated.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: add ability to get form type from Svelte' clearly and concisely describes the main feature addition of exposing a getFormType helper.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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 svelte-get-form-type

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

View your CI Pipeline Execution ↗ for commit 57953ed

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

☁️ Nx Cloud last updated this comment at 2026-05-08 22:23:08 UTC

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 8, 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 8, 2026

More templates

@tanstack/angular-form

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

@tanstack/form-core

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

@tanstack/form-devtools

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

@tanstack/lit-form

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

@tanstack/preact-form

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

@tanstack/react-form

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

@tanstack/react-form-devtools

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

@tanstack/react-form-nextjs

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

@tanstack/react-form-remix

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

@tanstack/react-form-start

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

@tanstack/solid-form

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

@tanstack/solid-form-devtools

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

@tanstack/svelte-form

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

@tanstack/vue-form

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

commit: 57953ed

@sentry
Copy link
Copy Markdown

sentry Bot commented May 8, 2026

Codecov Report

❌ Patch coverage is 0% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.66%. Comparing base (6892ed0) to head (57953ed).
⚠️ Report is 185 commits behind head on main.

Files with missing lines Patch % Lines
...ckages/svelte-form/src/createFormCreator.svelte.ts 0.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2159      +/-   ##
==========================================
- Coverage   90.35%   82.66%   -7.69%     
==========================================
  Files          38        8      -30     
  Lines        1752       75    -1677     
  Branches      444        4     -440     
==========================================
- Hits         1583       62    -1521     
+ Misses        149       12     -137     
+ Partials       20        1      -19     

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

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 (2)
packages/svelte-form/src/createFormCreator.svelte.ts (1)

270-315: ⚡ Quick win

Add a JSDoc warning that getFormType must only be used in a type position.

The function returns undefined as never at runtime, but its return type is non-nullable. TypeScript will not warn if a caller accidentally uses the result in a value position (e.g., formType.AppField(...)), which would produce a silent runtime TypeError. A JSDoc comment on the function makes the contract explicit.

📝 Suggested JSDoc addition
+  /**
+   * **Type inference helper only — never use the return value at runtime.**
+   *
+   * Call this function and use `typeof <result>` to derive the strongly typed
+   * form prop for a child component.  The runtime return value is always
+   * `undefined`; accessing any property on it will throw a `TypeError`.
+   *
+   * `@example`
+   * const formType = getFormType({ ...myFormOpts })
+   * // Only valid in type position:
+   * const { form }: { form: typeof formType } = $props()
+   */
   function getFormType<
🤖 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/svelte-form/src/createFormCreator.svelte.ts` around lines 270 - 315,
Add a JSDoc comment immediately above the getFormType function that clearly
warns this helper is for TypeScript type positions only and must not be used at
runtime (it returns `undefined as never`), e.g. a short paragraph stating "For
type-only use: do not call or access the returned value at runtime — use only in
type annotations/positions." Reference the function name getFormType and the
fact that its return is `undefined as never` so readers know why it would throw
if used as a value.
docs/framework/svelte/guides/form-composition.md (1)

295-340: ⚡ Quick win

"Reusing groups of fields" intentionally retains ReturnType<typeof createAppForm<...>> — worth a brief callout.

Right after introducing getFormType as the preferred approach, this section uses the old pattern without explanation. Readers may assume the section was overlooked. A short note clarifying why the ReturnType alias is still appropriate here (there is no shared formOptions to pass to getFormType; the group deliberately accepts any form with the required shape) would prevent confusion.

📝 Suggested clarifying note
 ## Reusing groups of fields in multiple forms

 Sometimes, a pair of fields are so closely related that it makes sense to group and reuse them — like the password example listed in the [linked fields guide](./linked-fields.md). Instead of repeating this logic across multiple forms, you can create reusable field group components.

+> Unlike the `getFormType` approach, which works with a specific shared `formOptions` object, reusable field groups often accept *any* form that satisfies a minimum shape. For that case, `ReturnType<typeof createAppForm<MinimalShape>>` is the right tool: it lets you declare the narrowed type inline without needing a dedicated `formOptions`.
+
 > Unlike form-level components, validators in field groups cannot be strictly typed and could be any value.
🤖 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 `@docs/framework/svelte/guides/form-composition.md` around lines 295 - 340, Add
a short clarifying note next to the PasswordFields example explaining why the
older ReturnType<typeof createAppForm<PasswordFields>> pattern is intentionally
used instead of getFormType: state that there are no shared formOptions to pass
to getFormType and this field-group intentionally accepts any form matching the
PasswordFields shape, so a simple ReturnType alias (AppForm) is appropriate;
reference the example names createAppForm, ReturnType, getFormType,
PasswordFields, and AppForm so readers understand the rationale.
🤖 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 `@docs/framework/svelte/guides/form-composition.md`:
- Around line 295-340: Add a short clarifying note next to the PasswordFields
example explaining why the older ReturnType<typeof
createAppForm<PasswordFields>> pattern is intentionally used instead of
getFormType: state that there are no shared formOptions to pass to getFormType
and this field-group intentionally accepts any form matching the PasswordFields
shape, so a simple ReturnType alias (AppForm) is appropriate; reference the
example names createAppForm, ReturnType, getFormType, PasswordFields, and
AppForm so readers understand the rationale.

In `@packages/svelte-form/src/createFormCreator.svelte.ts`:
- Around line 270-315: Add a JSDoc comment immediately above the getFormType
function that clearly warns this helper is for TypeScript type positions only
and must not be used at runtime (it returns `undefined as never`), e.g. a short
paragraph stating "For type-only use: do not call or access the returned value
at runtime — use only in type annotations/positions." Reference the function
name getFormType and the fact that its return is `undefined as never` so readers
know why it would throw if used as a value.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b07ac358-2fd7-48d6-8bc1-264ab23d160f

📥 Commits

Reviewing files that changed from the base of the PR and between 582386b and 57953ed.

📒 Files selected for processing (5)
  • docs/framework/svelte/guides/form-composition.md
  • examples/svelte/large-form/src/features/people/address-fields.svelte
  • examples/svelte/large-form/src/features/people/emergency-contact.svelte
  • examples/svelte/large-form/src/runes/form.ts
  • packages/svelte-form/src/createFormCreator.svelte.ts

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.

1 participant