34

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

7 Answers 7

34

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.

Sign up to request clarification or add additional context in comments.

6 Comments

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
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 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 😅
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.
Ah okay. I want the preview feature too. Are you maintainer of the vscode extension?
|
18

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

3 Comments

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
My custom event and class is called clickOutside, so it works for me.
worked perfectly @sveltejs/kit": "^2.0.0",
16

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;
    }
}

1 Comment

That's the only one actually working, should be marked as answer
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

2 Comments

Where do you put this?
@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.
7

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

Comments

1

You can now simply do

const dispatch = createEventDispatcher<{
    mounted: { id: string; store: FSStore }
    destroyed: { id: string }
  }>()

onMount(() => {
  dispatch('mounted', {
      id,
      store: fsStore,
  })
  return () => {
      dispatch('destroyed', {
        id,
      })
    }
})

This will then be fully typed:

<Explorer
  on:mounted={onExplorerMount}
  on:destroyed={onExplorerDestroy}
/>

ide preview

Comments

1

The solution provided by Jonathan did the trick for me, but I found a little improvement that will provide autocomplete for the event.details if you need it:

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

    declare namespace svelteHTML {
        interface HTMLAttributes {
            'on:remove'?: (event: CustomEvent<{ itemId: string }>) => void;
        }
    }
}

export {};

And here’s the official documentation for reference.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.