27

I'm using clickOutside directive on my svelte-typescript project and I'm getting this error when I assign custom event to the related element

Type '{ class: string; onclick_outside: () => boolean; }' is not assignable to type 'HTMLProps<HTMLDivElement>'.
  Property 'onclick_outside' does not exist on type 'HTMLProps<HTMLDivElement>'

here's a snippet of my code

{#if profileToolbar}
<div
    transition:fly={{ y: -20, duration: 300 }}
    use:clickOutside={profileToolbarContainer}
    on:click_outside={() => (profileToolbar = !profileToolbar)}
    class="origin-top-right absolute right-0 mt-2 w-48 rounded-md
    shadow-lg z-10 shadow-md">

this is the clickOutside directive that I'm using currently https://svelte.dev/repl/0ace7a508bd843b798ae599940a91783?version=3.16.7

I'm new to typescript so I don't really know where to start with my google search, anyone knows how to tackle this issue? thanks for your help

KawishBit
  • 650
  • 1
  • 8
  • 18

5 Answers5

33

According to the doc, you can create a .d.ts file in your project somewhere. And put inside that file the following:

declare namespace svelte.JSX {
  interface HTMLAttributes<T> {
    onclick_outside: () => void
  }
}

Please read the doc for more detail.

hackape
  • 18,643
  • 2
  • 29
  • 57
  • 1
    Works perfectly!, i just need to change it to `interface HTMLProps`, thanks for the help and the advice man, i'm aware that svelte typescript is still new, but unfortunately i'm not the one making the decision atm, but i'll make sure to remember your words – KawishBit Sep 30 '20 at 11:56
  • To hackape: I know this is a little off topic, but could you share some of the other inconveniences you experienced while using Svelte with TS? I'm one of the maintainers in that area and feedback like this is really valuable (because it's rare). – dummdidumm Oct 02 '20 at 06:47
  • @dummdidumm I know bridging the two is not easy, so kudos to the work! But sorry I don’t have much to share cus it was more than half a year ago and I don’t remember much about specific things. I can only remember the general impression about the experience was acceptable, but not totally satisfying. At the end of day I thought to myself better just keep the TS things in `.ts` file as much as possible and import into `.svelte` file to lessen the melange and ignore warnings. Later on I switch back to the comfort world of react – hackape Oct 02 '20 at 10:24
  • I was trying to port the svelte repl into vscode extension, but got interrupted then dropped it halfway. I can find time to dust off and refresh my memory. If I have anything worth sharing I’ll get back to you. – hackape Oct 02 '20 at 10:29
  • Thanks for the quick response! Things should be better now half a year later, but I agree that there are still some rough edges. About your REPL: In case you only want the "show compiled output" behavior of the REPL, that is now possible through the Svelte for VS Code extension. Command is "Svelte: Show Compiled Code". – dummdidumm Oct 02 '20 at 10:32
  • 1
    Ah okay. I want the preview feature too. Are you maintainer of the vscode extension? – hackape Oct 02 '20 at 10:36
16

This declaration worked for me

declare namespace svelte.JSX {
  interface DOMAttributes<T> {
    onclick_outside?: CompositionEventHandler<T>;
  }
}

Don't forget to specify the location of your custom type declarations in tsconfig.json

Tomasz
  • 657
  • 3
  • 9
  • Where do you put this? – Marcus Jul 10 '21 at 13:49
  • 1
    @Marcus and future readers: SvelteKit comes with a `app.d.ts` inside the `src` folder. That's a fine location, also if you're using "plain" Svelte. In comparison, Angular used to generate a `typings.d.ts` in its `src` folder for the same purpose. – J.P. Mar 05 '22 at 19:23
15

Ok, so existing answers did work only partly for me. Given that the clickOutside action fires a custom event named click_outside i arrive at following solution:

declare namespace svelte.JSX {
    interface HTMLProps<T> {
        onclick_outside?: (e: CustomEvent) => void;
    }
}
oae
  • 1,513
  • 1
  • 17
  • 23
5

For me the following worked:

declare namespace svelteHTML {
    interface HTMLAttributes<T> {
        "on:click_outside"?: CompositionEventHandler<T>;
    }
}

inside your src/app.d.ts.

based on this

Teiem
  • 1,329
  • 15
  • 32
5

Update 7/23/23

New SvelteKit requires this:

Here is my src/app.d.ts file.

// See https://kit.svelte.dev/docs/types#app
// for information about these interfaces
declare global {
    namespace App {
        // interface Error {}
        // interface Locals {}
        // interface PageData {}
        // interface Platform {}
    }

    declare namespace svelteHTML {
        interface HTMLAttributes<T> {
            'on:clickOutside'?: CompositionEventHandler<T>;
        }
    }
}

export { };

J

Jonathan
  • 3,893
  • 5
  • 46
  • 77
  • For those looking at this answer: A gotcha in this new format is that the property includes the colon `:` in the property name. So `on:clickOutside` instead of `onclickOutside` – Coo Jul 26 '23 at 06:08
  • My custom event and class is called `clickOutside`, so it works for me. – Jonathan Jul 26 '23 at 11:04