Pinkney
Pinkney

Reputation: 163

Svelte form on:submit type TypeScript

I am trying to build a simple form in Svelte TypeScript.

My on:submit looks like this: <form on:submit={onSubmit}>, and my onSubmit function is defined as:

const onSubmit = (event: HTMLFormElement) => {
    event.preventDefault();
    dispatch("addPerson", person);
    person = {
      name: "",
      isOwed: 0,
    };
  };

With this code I get the TypeScript problem:

Type '(event: HTMLFormElement) => void' is not assignable to type 'EventHandler<Event, HTMLFormElement>'. Types of parameters 'event' and 'event' are incompatible.

I get that the event passed to onSubmit has the type EventHandler<Event, HTMLFormElement>, and that my function is only expecting HTMLFormElement, but I can't manage to expect the whole EventHandler object. How can I achieve this?

Upvotes: 9

Views: 8226

Answers (4)

Ale
Ale

Reputation: 2022

As @coldbreathe suggested in another answer, the most straightforward way seems to be annotating the handler function instead:

<script lang="ts">
  import type { EventHandler } from "svelte/elements";

  const handleSubmit: EventHandler<SubmitEvent, HTMLFormElement> =
    function (event) {
      const data = new FormData(event.currentTarget);
      // event.currentTarget will have type HTMLFormElement here
    };
</script>

<form on:submit|preventDefault={handleSubmit}>
  <!-- ... -->
</form>

EventHandler<E, T> here basically says that event will have type E and event.currentTarget will have type T. Here’s the actual definition:

type EventHandler<E extends Event = Event, T extends EventTarget = Element> = (
    event: E & { currentTarget: EventTarget & T }
) => any;

Why currentTarget and not just target?

EventHandler annotation doesn’t doesn’t change type of event.target – that’s because it could have bubbled from an element of any another type. It’s not something that should ever occur with SubmitEvent in particular, but for other events it’s possible.

Rule of thumb: for consistency, just use currentTarget, unless you need target for some reason.

Upvotes: 0

coldbreathe
coldbreathe

Reputation: 91

Try this instead.

<script lang="ts">    
      const handleSubmit: svelte.JSX.EventHandler<Event, HTMLFormElement> = () => {

      }
</script>

<form on:submit|preventDefault={handleSubmit}>

</form>

Upvotes: 4

Zach Olivare
Zach Olivare

Reputation: 4161

The event type is a SubmitEvent.

function handleSubmit(e: SubmitEvent) {
 const formData = new FormData(e.target as HTMLFormElement)
}
<form on:submit|preventDefault={handleSubmit}>

Upvotes: 13

johannchopin
johannchopin

Reputation: 14873

The event parameter is an Event, not a HTMLFormElement HTML node. So you can replace event: HTMLFormElement to event: Event or even better (as suggested by TypeScript): event: EventHandler<Event, HTMLFormElement>.

Upvotes: 1

Related Questions