Skip to content

Non-fancy event delegation syntax (on:click etc.) not working with Typescript? #1939

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
earslap opened this issue Oct 31, 2023 · 5 comments · Fixed by ryansolid/dom-expressions#354
Labels
enhancement New feature or request typescript relating to typescript or types

Comments

@earslap
Copy link

earslap commented Oct 31, 2023

Describe the bug

The syntax for creating native event handlers (the ones prefixed with on: ) gives type errors.

Your Example Website or App

https://playground.solidjs.com/anonymous/c04dc47c-bac3-45bb-8114-9d520029b79f

Steps to Reproduce the Bug or Issue

Just visit https://playground.solidjs.com/anonymous/c04dc47c-bac3-45bb-8114-9d520029b79f and the error is visible.

Expected behavior

I expect the code to compile.

Same issue here: #1786 (comment)

@ryansolid
Copy link
Member

The intention for this originally was for custom events so you would add them by extending the interface. I suppose they could be added to the base types.

@ryansolid ryansolid added the enhancement New feature or request label Oct 31, 2023
@earslap
Copy link
Author

earslap commented Oct 31, 2023

To me, the documentation makes it sound like they are supported out of the box for the natively existing events. This also applies to oncapture: variants BTW. I think they work, just not compile without errors. Do you know of a simple example for how the interface extension might ideally be done at application level? Maybe I can add a simple example to the docs at the very least. The info I found so far resides here: https://docs.solidjs.com/references/api-reference/special-jsx-attributes/on_-and-oncapture_

@mdynnl
Copy link
Contributor

mdynnl commented Nov 11, 2023

@earslap you can refer back to the old docs before the news docs is ready

https://www.solidjs.com/guides/typescript#special-jsx-attributes-and-directives

class NameEvent extends CustomEvent {
  type: 'Name';
  detail: {name: string};

  constructor(name: string) {
    super('Name', {detail: {name}});
  }
}

declare module "solid-js" {
  namespace JSX {
    interface CustomEvents { // on:Name
      "Name": NameEvent;
    }
    interface CustomCaptureEvents { // oncapture:Name
      "Name": NameEvent;
    }
  }
}

<div on:Name={(event) => console.log('name is', event.detail.name)}/>

@ryansolid ryansolid added the typescript relating to typescript or types label Nov 22, 2023
@sparecycles
Copy link

Any reason not to have a default catch-all, e.g.,

declare module "solid-js" {
  namespace JSX {
    interface CustomEvents {
      [on: string]: Event;
    }
    interface CustomCaptureEvents {
      [oncapture: string]: Event;
    }
  }
}

?

@KotoriK
Copy link

KotoriK commented Aug 7, 2024

I agree with that the type definition should be right out of the box since it is the only way now to disable Event Delegation (refers to the doc). Moreover, Event Delegation disabling is not a uncommon demand. For the use case of embedding components on other pages, global injecting may leads to unpredictable behaviours since it pollutes global environment.

From user side, an probably elegant types might be:

// global.d.ts
import { JSX } from "solid-js";
type GetEventName<T extends string> = T extends `on${infer R}` ? R : never;
type ExtractEvent<T> = T extends JSX.EventHandlerUnion<any, infer E> ? E : Event;
type EventPair<T> = {
  [K in keyof Required<JSX.CustomEventHandlersLowerCase<T>>]: [GetEventName<K>,ExtractEvent<Required<JSX.CustomEventHandlersLowerCase<T>>[K]>];
}[keyof JSX.CustomEventHandlersLowerCase<T>]
type FromEntries<T extends [any,any]> = {
    [K in T[0]]: T extends [K,infer V] ? V : never
}
type HTMLElementEventsMap = FromEntries<EventPair<HTMLElement>>
declare module "solid-js" {
    namespace JSX {
      interface CustomEvents extends HTMLElementEventsMap {
      }
    }
  }

These declarations extract official definition automatically. However, things can be done better from lib side. I would like to help if you need.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request typescript relating to typescript or types
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants