Skip to content

Fix onSubmit type inference#71

Open
Huliiiiii wants to merge 1 commit intoopen-circle:mainfrom
Huliiiiii:unify-handler
Open

Fix onSubmit type inference#71
Huliiiiii wants to merge 1 commit intoopen-circle:mainfrom
Huliiiiii:unify-handler

Conversation

@Huliiiiii
Copy link

@Huliiiiii Huliiiiii commented Mar 7, 2026

Alternative to #64

Summary by CodeRabbit

  • Breaking Changes

    • Form component's onSubmit property type has been simplified across all frameworks (Preact, React, Qwik, Solid, Svelte, Vue). The property now strictly accepts a single handler type.
  • Documentation

    • API documentation updated to reflect the Form component's onSubmit property changes across all framework implementations.

Copilot AI review requested due to automatic review settings March 7, 2026 02:38
@vercel
Copy link

vercel bot commented Mar 7, 2026

@Huliiiiii is attempting to deploy a commit to the Open Circle Team on Vercel.

A member of the Team first needs to authorize it.

@dosubot dosubot bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Mar 7, 2026
@coderabbitai
Copy link

coderabbitai bot commented Mar 7, 2026

📝 Walkthrough

Walkthrough

The FormProps onSubmit property type is narrowed across all framework implementations (Preact, Qwik, React, Solid, Svelte, Vue) by removing the SubmitHandler<TSchema> union member, leaving only SubmitEventHandler<TSchema>. Corresponding API documentation files are updated to reflect this type change.

Changes

Cohort / File(s) Summary
Framework Form Components
frameworks/preact/src/components/Form/Form.tsx, frameworks/qwik/src/components/Form/Form.tsx, frameworks/react/src/components/Form/Form.tsx, frameworks/solid/src/components/Form/Form.tsx, frameworks/svelte/src/components/Form/Form.svelte, frameworks/vue/src/components/Form/Form.vue
Narrowed onSubmit (or onSubmit$ for Qwik) property type from union SubmitHandler<TSchema> | SubmitEventHandler<TSchema> to single SubmitEventHandler<TSchema>. Removed SubmitHandler type import from all implementations.
Website API Documentation
website/src/routes/(docs)/{preact,qwik,react,solid,svelte,vue}/api/(components)/Form/properties.ts
Updated type documentation for onSubmit property, replacing union-based type structure with single custom type SubmitEventHandler, including updated href and simplified generics definitions.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 The union splits, a cleaner way,
Two types became one today,
SubmitHandler bids farewell,
SubmitEventHandler rings the bell!
Across all frameworks, types align,
Our narrowed paths now gently shine. 🌟

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Fix onSubmit type inference' directly describes the main change across all modified files: narrowing the onSubmit prop type from a union of SubmitHandler and SubmitEventHandler to only SubmitEventHandler.
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
  • Post copyable unit tests in a comment

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


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.

@dosubot dosubot bot added the fix Smaller bug fix or improvement label Mar 7, 2026
@Huliiiiii
Copy link
Author

Huliiiiii commented Mar 7, 2026

@fabian-hiller Could you please check whether there are any errors? This should be safe.

I've manually checked it, and there were no issues in any case.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Updates Form component onSubmit prop typing (and corresponding docs) to improve TypeScript inference by using a single SubmitEventHandler<TSchema> type instead of a SubmitHandler | SubmitEventHandler union.

Changes:

  • Changed onSubmit/onsubmit prop types across framework Form components to SubmitEventHandler<TSchema> (and Qwik to QRL<SubmitEventHandler<TSchema>>).
  • Updated website API property definitions to match the new onSubmit type shape.
  • Removed now-unused SubmitHandler imports from framework Form components.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated no comments.

Show a summary per file
File Description
website/src/routes/(docs)/vue/api/(components)/Form/properties.ts Docs: onSubmit now documented as SubmitEventHandler<TSchema>
website/src/routes/(docs)/svelte/api/(components)/Form/properties.ts Docs: onsubmit now documented as SubmitEventHandler<TSchema>
website/src/routes/(docs)/solid/api/(components)/Form/properties.ts Docs: onSubmit now documented as SubmitEventHandler<TSchema>
website/src/routes/(docs)/react/api/(components)/Form/properties.ts Docs: onSubmit now documented as SubmitEventHandler<TSchema>
website/src/routes/(docs)/qwik/api/(components)/Form/properties.ts Docs: onSubmit$ now documented as QRL<SubmitEventHandler<TSchema>>
website/src/routes/(docs)/preact/api/(components)/Form/properties.ts Docs: onSubmit now documented as SubmitEventHandler<TSchema>
frameworks/vue/src/components/Form/Form.vue Vue FormProps onSubmit narrowed to SubmitEventHandler<TSchema>
frameworks/svelte/src/components/Form/Form.svelte Svelte FormProps onsubmit narrowed to SubmitEventHandler<TSchema>
frameworks/solid/src/components/Form/Form.tsx Solid FormProps onSubmit narrowed to SubmitEventHandler<TSchema>
frameworks/react/src/components/Form/Form.tsx React FormProps onSubmit narrowed to SubmitEventHandler<TSchema>
frameworks/qwik/src/components/Form/Form.tsx Qwik FormProps onSubmit$ narrowed to QRL<SubmitEventHandler<TSchema>>
frameworks/preact/src/components/Form/Form.tsx Preact FormProps onSubmit narrowed to SubmitEventHandler<TSchema>

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

@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

🧹 Nitpick comments (5)
frameworks/solid/src/components/Form/Form.tsx (1)

13-29: Consider using interface for FormProps.

Per coding guidelines, interface is preferred over type for defining object shapes.

♻️ Suggested refactor
-export type FormProps<TSchema extends Schema = Schema> = Omit<
-  JSX.FormHTMLAttributes<HTMLFormElement>,
-  'onSubmit' | 'novalidate' | 'noValidate'
-> & {
+export interface FormProps<TSchema extends Schema = Schema>
+  extends Omit<
+    JSX.FormHTMLAttributes<HTMLFormElement>,
+    'onSubmit' | 'novalidate' | 'noValidate'
+  > {
   /**
    * The form store instance.
    */
   readonly of: FormStore<TSchema>;
   /**
    * The child elements to render within the form.
    */
   readonly children: JSX.Element;
   /**
    * The submit handler called when the form is submitted and validation succeeds.
    */
   readonly onSubmit: SubmitEventHandler<TSchema>;
-};
+}

As per coding guidelines: "Prefer interface over type for defining object shapes in TypeScript".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frameworks/solid/src/components/Form/Form.tsx` around lines 13 - 29, The
declaration for FormProps should be an interface rather than a type alias;
replace the "export type FormProps<TSchema extends Schema = Schema> =
Omit<JSX.FormHTMLAttributes<HTMLFormElement>, 'onSubmit' | 'novalidate' |
'noValidate'> & { ... }" with an exported interface named FormProps that extends
Omit<JSX.FormHTMLAttributes<HTMLFormElement>, 'onSubmit' | 'novalidate' |
'noValidate'> and preserves the generic parameter TSchema (with its default),
readonly properties (of: FormStore<TSchema>, children: JSX.Element) and the
onSubmit: SubmitEventHandler<TSchema> member so the shape and types remain
identical.
frameworks/react/src/components/Form/Form.tsx (1)

13-25: Consider using interface for FormProps.

Per coding guidelines, interface is preferred over type for defining object shapes in TypeScript. Since FormProps defines an object shape, consider converting it.

♻️ Suggested refactor
-export type FormProps<TSchema extends Schema = Schema> = Omit<
-  FormHTMLAttributes<HTMLFormElement>,
-  'onSubmit' | 'novalidate' | 'noValidate'
-> & {
+export interface FormProps<TSchema extends Schema = Schema>
+  extends Omit<
+    FormHTMLAttributes<HTMLFormElement>,
+    'onSubmit' | 'novalidate' | 'noValidate'
+  > {
   /**
    * The form store instance.
    */
   readonly of: FormStore<TSchema>;
   /**
    * The submit handler called when the form is submitted and validation succeeds.
    */
   readonly onSubmit: SubmitEventHandler<TSchema>;
-};
+}

As per coding guidelines: "Prefer interface over type for defining object shapes in TypeScript".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frameworks/react/src/components/Form/Form.tsx` around lines 13 - 25, Convert
the FormProps type alias into an interface while preserving its generic
parameter and the omitted form attributes; specifically, replace "export type
FormProps<TSchema extends Schema = Schema> = Omit<...> & { ... }" with an
"export interface FormProps<TSchema extends Schema = Schema> extends
Omit<FormHTMLAttributes<HTMLFormElement>, 'onSubmit' | 'novalidate' |
'noValidate'> { readonly of: FormStore<TSchema>; readonly onSubmit:
SubmitEventHandler<TSchema>; }" so the shape, readonly modifiers, generic
constraint, and referenced symbols (FormProps, Schema, FormStore,
SubmitEventHandler) remain identical but use interface syntax.
frameworks/svelte/src/components/Form/Form.svelte (1)

15-31: Consider using interface for FormProps.

Per coding guidelines, interface is preferred over type for defining object shapes.

♻️ Suggested refactor
-  export type FormProps<TSchema extends Schema = Schema> = Omit<
-    HTMLFormAttributes,
-    'on:submit' | 'onsubmit' | 'novalidate'
-  > & {
+  export interface FormProps<TSchema extends Schema = Schema>
+    extends Omit<
+      HTMLFormAttributes,
+      'on:submit' | 'onsubmit' | 'novalidate'
+    > {
     /**
      * The form store instance.
      */
     of: FormStore<TSchema>;
     /**
      * The submit handler called when the form is submitted and validation succeeds.
      */
     onsubmit: SubmitEventHandler<TSchema>;
     /**
      * The child elements to render within the form.
      */
     children: Snippet;
-  };
+  }

As per coding guidelines: "Prefer interface over type for defining object shapes in TypeScript".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frameworks/svelte/src/components/Form/Form.svelte` around lines 15 - 31,
Replace the exported FormProps type alias with an exported interface named
FormProps that keeps the generic parameter TSchema extends Schema and extends
the same Omit<HTMLFormAttributes, 'on:submit' | 'onsubmit' | 'novalidate'>, and
include the same properties (of: FormStore<TSchema>, onsubmit:
SubmitEventHandler<TSchema>, children: Snippet) so all references to FormProps,
FormStore, SubmitEventHandler continue to work; essentially convert the "export
type FormProps<...> = ..." declaration into an "export interface FormProps<...>
extends ..." declaration preserving the exact shape and generics.
frameworks/preact/src/components/Form/Form.tsx (1)

13-25: Consider using interface for FormProps.

Per coding guidelines, interface is preferred over type for defining object shapes.

♻️ Suggested refactor
-export type FormProps<TSchema extends Schema = Schema> = Omit<
-  JSX.FormHTMLAttributes<HTMLFormElement>,
-  'onSubmit' | 'novalidate' | 'noValidate'
-> & {
+export interface FormProps<TSchema extends Schema = Schema>
+  extends Omit<
+    JSX.FormHTMLAttributes<HTMLFormElement>,
+    'onSubmit' | 'novalidate' | 'noValidate'
+  > {
   /**
    * The form store instance.
    */
   readonly of: FormStore<TSchema>;
   /**
    * The submit handler called when the form is submitted and validation succeeds.
    */
   readonly onSubmit: SubmitEventHandler<TSchema>;
-};
+}

As per coding guidelines: "Prefer interface over type for defining object shapes in TypeScript".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frameworks/preact/src/components/Form/Form.tsx` around lines 13 - 25, Replace
the FormProps type alias with an equivalent interface to follow the coding
guideline; keep the same shape and generics (TSchema extends Schema) and
preserve the inheritance from Omit<JSX.FormHTMLAttributes<HTMLFormElement>,
'onSubmit' | 'novalidate' | 'noValidate'> as well as the readonly properties of
of: FormStore<TSchema> and onSubmit: SubmitEventHandler<TSchema>; update any
exports/usages to reference the new FormProps interface name but leave
FormStore, SubmitEventHandler, and Schema identifiers unchanged.
frameworks/qwik/src/components/Form/Form.tsx (1)

14-26: Prefer an interface for exported props.

FormProps is an exported object shape, and this block is already being touched.

♻️ Suggested refactor
-export type FormProps<TSchema extends Schema = Schema> = Omit<
-  PropsOf<'form'>,
-  'onSubmit$' | 'noValidate'
-> & {
+export interface FormProps<TSchema extends Schema = Schema>
+  extends Omit<PropsOf<'form'>, 'onSubmit$' | 'noValidate'> {
   /**
    * The form store instance.
    */
   readonly of: FormStore<TSchema>;
   /**
    * The submit handler called when the form is submitted and validation succeeds.
    */
   readonly onSubmit$: QRL<SubmitEventHandler<TSchema>>;
-};
+}

As per coding guidelines, "Prefer interface over type for defining object shapes in TypeScript".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frameworks/qwik/src/components/Form/Form.tsx` around lines 14 - 26, Replace
the exported type alias FormProps<TSchema extends Schema = Schema> with an
exported interface declaration so the prop shape uses an interface; declare
"export interface FormProps<TSchema extends Schema = Schema> extends
Omit<PropsOf<'form'>, 'onSubmit$' | 'noValidate'> { readonly of:
FormStore<TSchema>; readonly onSubmit$: QRL<SubmitEventHandler<TSchema>>; }"
preserving the same generic constraint, Omit, readonly modifiers, and member
names (FormProps, TSchema, Schema, PropsOf<'form'>, FormStore, QRL,
SubmitEventHandler) so the public API and types remain identical while switching
to an interface.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@frameworks/react/src/components/Form/Form.tsx`:
- Line 24: Add a migration doc entry explaining the breaking change where Form's
onSubmit prop type was tightened from SubmitHandler<TSchema> |
SubmitEventHandler<TSchema> to only SubmitEventHandler<TSchema>; state that
handlers must now accept the event parameter (the form submit event) so callers
should change signatures from (data) => { ... } to (data, event) => { ... };
include a short rationale referencing the Form component and its onSubmit prop
and mention that `@formisch/methods`' handleSubmit still accepts both
SubmitHandler and SubmitEventHandler for backward compatibility; provide a small
migration snippet suggestion and a note that this change was introduced in
v0.4.0 (CHANGELOG: "Update `Form` component submit handler types").

---

Nitpick comments:
In `@frameworks/preact/src/components/Form/Form.tsx`:
- Around line 13-25: Replace the FormProps type alias with an equivalent
interface to follow the coding guideline; keep the same shape and generics
(TSchema extends Schema) and preserve the inheritance from
Omit<JSX.FormHTMLAttributes<HTMLFormElement>, 'onSubmit' | 'novalidate' |
'noValidate'> as well as the readonly properties of of: FormStore<TSchema> and
onSubmit: SubmitEventHandler<TSchema>; update any exports/usages to reference
the new FormProps interface name but leave FormStore, SubmitEventHandler, and
Schema identifiers unchanged.

In `@frameworks/qwik/src/components/Form/Form.tsx`:
- Around line 14-26: Replace the exported type alias FormProps<TSchema extends
Schema = Schema> with an exported interface declaration so the prop shape uses
an interface; declare "export interface FormProps<TSchema extends Schema =
Schema> extends Omit<PropsOf<'form'>, 'onSubmit$' | 'noValidate'> { readonly of:
FormStore<TSchema>; readonly onSubmit$: QRL<SubmitEventHandler<TSchema>>; }"
preserving the same generic constraint, Omit, readonly modifiers, and member
names (FormProps, TSchema, Schema, PropsOf<'form'>, FormStore, QRL,
SubmitEventHandler) so the public API and types remain identical while switching
to an interface.

In `@frameworks/react/src/components/Form/Form.tsx`:
- Around line 13-25: Convert the FormProps type alias into an interface while
preserving its generic parameter and the omitted form attributes; specifically,
replace "export type FormProps<TSchema extends Schema = Schema> = Omit<...> & {
... }" with an "export interface FormProps<TSchema extends Schema = Schema>
extends Omit<FormHTMLAttributes<HTMLFormElement>, 'onSubmit' | 'novalidate' |
'noValidate'> { readonly of: FormStore<TSchema>; readonly onSubmit:
SubmitEventHandler<TSchema>; }" so the shape, readonly modifiers, generic
constraint, and referenced symbols (FormProps, Schema, FormStore,
SubmitEventHandler) remain identical but use interface syntax.

In `@frameworks/solid/src/components/Form/Form.tsx`:
- Around line 13-29: The declaration for FormProps should be an interface rather
than a type alias; replace the "export type FormProps<TSchema extends Schema =
Schema> = Omit<JSX.FormHTMLAttributes<HTMLFormElement>, 'onSubmit' |
'novalidate' | 'noValidate'> & { ... }" with an exported interface named
FormProps that extends Omit<JSX.FormHTMLAttributes<HTMLFormElement>, 'onSubmit'
| 'novalidate' | 'noValidate'> and preserves the generic parameter TSchema (with
its default), readonly properties (of: FormStore<TSchema>, children:
JSX.Element) and the onSubmit: SubmitEventHandler<TSchema> member so the shape
and types remain identical.

In `@frameworks/svelte/src/components/Form/Form.svelte`:
- Around line 15-31: Replace the exported FormProps type alias with an exported
interface named FormProps that keeps the generic parameter TSchema extends
Schema and extends the same Omit<HTMLFormAttributes, 'on:submit' | 'onsubmit' |
'novalidate'>, and include the same properties (of: FormStore<TSchema>,
onsubmit: SubmitEventHandler<TSchema>, children: Snippet) so all references to
FormProps, FormStore, SubmitEventHandler continue to work; essentially convert
the "export type FormProps<...> = ..." declaration into an "export interface
FormProps<...> extends ..." declaration preserving the exact shape and generics.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 191ddf9b-d264-48c3-87d4-731b39faffce

📥 Commits

Reviewing files that changed from the base of the PR and between d591cf7 and e77f355.

📒 Files selected for processing (12)
  • frameworks/preact/src/components/Form/Form.tsx
  • frameworks/qwik/src/components/Form/Form.tsx
  • frameworks/react/src/components/Form/Form.tsx
  • frameworks/solid/src/components/Form/Form.tsx
  • frameworks/svelte/src/components/Form/Form.svelte
  • frameworks/vue/src/components/Form/Form.vue
  • website/src/routes/(docs)/preact/api/(components)/Form/properties.ts
  • website/src/routes/(docs)/qwik/api/(components)/Form/properties.ts
  • website/src/routes/(docs)/react/api/(components)/Form/properties.ts
  • website/src/routes/(docs)/solid/api/(components)/Form/properties.ts
  • website/src/routes/(docs)/svelte/api/(components)/Form/properties.ts
  • website/src/routes/(docs)/vue/api/(components)/Form/properties.ts

@fabian-hiller
Copy link
Member

That's actually a good idea! Thanks for the PR!

@fabian-hiller fabian-hiller self-assigned this Mar 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fix Smaller bug fix or improvement size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants