Is there no SubmitEvent interface in Typescript?

7.9k views Asked by At

TypeScript has different interfaces mapping DOM events. (e.g. KeyboardEvent, MouseEvent, etc.). We can find them here. For instance, they are handy in Angular when receiving an event's payload in an event listener.

I have been a bit surprised to be unable to find an interface for the SubmitEvent which is described here.

Can anyone confirm and explain why? I would expect the TypeScript team to share interfaces for every DOM event.

3

There are 3 answers

0
He Nrik On

Safari doesn't seem to have implemented the SubmitEvent. That might be the reason why typescript has not created an interface for it. (I'm speculating.)

The only thing SubmitEvent is bringing to the table is submitter. That's the part that I was missing... I need Safari support, so I need to do a hack. Not just an interface-hack.

If someone has more info why it's not supported in Safari, please tell me.

References:

0
Oleg Valter is with Ukraine On

TypeScript 4.4 added some missing interfaces to the standard definitions library, which now includes SubmitEvent interface defined as follows:

interface SubmitEvent extends Event {
    /**
     * Returns the element representing the submit button that triggered the form submission, or null if the submission was not triggered by a button.
     */
    readonly submitter: HTMLElement | null;
}

A type assertion should work out-of-the-box without any extra setup:

{
    const form = document.querySelector<HTMLFormElement>("form");
    form?.addEventListener("submit", (event) => {
        const { submitter } = event as SubmitEvent;
        console.log(submitter?.id);
    });
}

Playground

Unfortunately, the new interface is not added neither to the HTMLElementEventMap interface nor via an overload to the addEventListener method, so you will have to utilize declaration merging if you want a more seamless experience (for the onsubmit version, see Fenton's answer):

interface HTMLFormElement {
    addEventListener(type: "submit", listener: (this: HTMLFormElement, ev: SubmitEvent) => any, options?: boolean | AddEventListenerOptions): void;
}

{
    const form = document.querySelector<HTMLFormElement>("form");
    form?.addEventListener("submit", ({ submitter }) => {
        console.log(submitter?.id);
    });
}

Playground

2
Fenton On

These do tend to get added over time. At the moment it is marked in the standard as "single implementation only", so it is more likely to be added when it has better adoption. (I believe it is in two engines now, so the standard will be updated to reflect that soon, I believe, as it will be in Chromium and Gecko).

You can use Event in all cases, unless you actually need to use the newer submitter, which is the only addition the SubmitEvent brings to the table.

If you do need submitter, you can easily create your SubmitEvent and adjust the HTMLFormElement to use it - as shown below.

interface SubmitEvent extends Event {
  submitter: HTMLElement; 
}

interface HTMLFormElement {
  onsubmit: (this: GlobalEventHandlers, ev: SubmitEvent) => any | null;
}

When the library is updated, you'll be warned that submitter is already declared and you can delete your temporary interface.