Skip to content

Commit b7e5a6c

Browse files
committed
fix: better types for on
- give autocompletion for types and more precise event types for html elements - allow to pass other kinds of event target nodes, like window closes #12027 fixes #12045
1 parent 59486be commit b7e5a6c

File tree

4 files changed

+69
-6
lines changed

4 files changed

+69
-6
lines changed

.changeset/rare-insects-tell.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"svelte": patch
3+
---
4+
5+
fix: better types for `on`

packages/svelte/src/internal/client/dom/elements/events.js

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export function replay_events(dom) {
3333

3434
/**
3535
* @param {string} event_name
36-
* @param {Element} dom
36+
* @param {EventTarget} dom
3737
* @param {EventListener} handler
3838
* @param {AddEventListenerOptions} options
3939
*/
@@ -71,7 +71,31 @@ export function create_event(event_name, dom, handler, options) {
7171
* rather than `addEventListener` will preserve the correct order relative to handlers added declaratively
7272
* (with attributes like `onclick`), which use event delegation for performance reasons
7373
*
74+
* @template {HTMLElement} Element
75+
* @template {keyof HTMLElementEventMap} Type
76+
* @overload
7477
* @param {Element} element
78+
* @param {Type} type
79+
* @param {(this: Element, event: HTMLElementEventMap[Type]) => any} handler
80+
* @param {AddEventListenerOptions} [options]
81+
* @returns {() => void}
82+
*/
83+
84+
/**
85+
* Attaches an event handler to an element and returns a function that removes the handler. Using this
86+
* rather than `addEventListener` will preserve the correct order relative to handlers added declaratively
87+
* (with attributes like `onclick`), which use event delegation for performance reasons
88+
*
89+
* @overload
90+
* @param {EventTarget} element
91+
* @param {string} type
92+
* @param {EventListener} handler
93+
* @param {AddEventListenerOptions} [options]
94+
* @returns {() => void}
95+
*/
96+
97+
/**
98+
* @param {EventTarget} element
7599
* @param {string} type
76100
* @param {EventListener} handler
77101
* @param {AddEventListenerOptions} [options]
@@ -119,12 +143,12 @@ export function delegate(events) {
119143
}
120144

121145
/**
122-
* @param {Node} handler_element
146+
* @param {EventTarget} handler_element
123147
* @param {Event} event
124148
* @returns {void}
125149
*/
126150
export function handle_event_propagation(handler_element, event) {
127-
var owner_document = handler_element.ownerDocument;
151+
var owner_document = /** @type {Node} */ (handler_element).ownerDocument;
128152
var event_name = event.type;
129153
var path = event.composedPath?.() || [];
130154
var current_target = /** @type {null | Element} */ (path[0] || event.target);

packages/svelte/tests/types/events.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { on } from 'svelte/events';
2+
3+
// ---------------- on
4+
5+
on(document.body, 'click', (e) => e.button);
6+
7+
on(
8+
document.body,
9+
'clidck',
10+
(e) =>
11+
// @ts-expect-error
12+
e.button
13+
);
14+
15+
on(
16+
window,
17+
'click',
18+
(e) =>
19+
// @ts-expect-error ideally we'd know this is a MouseEvent here, too, but for keeping the types sane, we currently don't
20+
e.button
21+
);
22+
23+
on(
24+
// @ts-expect-error
25+
'asd',
26+
'asd',
27+
(e) => e
28+
);

packages/svelte/types/index.d.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2350,9 +2350,15 @@ declare module 'svelte/events' {
23502350
* rather than `addEventListener` will preserve the correct order relative to handlers added declaratively
23512351
* (with attributes like `onclick`), which use event delegation for performance reasons
23522352
*
2353-
*
2354-
*/
2355-
export function on(element: Element, type: string, handler: EventListener, options?: AddEventListenerOptions | undefined): () => void;
2353+
* */
2354+
export function on<Element extends HTMLElement, Type extends keyof HTMLElementEventMap>(element: Element, type: Type, handler: (this: Element, event: HTMLElementEventMap[Type]) => any, options?: AddEventListenerOptions | undefined): () => void;
2355+
/**
2356+
* Attaches an event handler to an element and returns a function that removes the handler. Using this
2357+
* rather than `addEventListener` will preserve the correct order relative to handlers added declaratively
2358+
* (with attributes like `onclick`), which use event delegation for performance reasons
2359+
*
2360+
* */
2361+
export function on(element: EventTarget, type: string, handler: EventListener, options?: AddEventListenerOptions | undefined): () => void;
23562362
}
23572363

23582364
declare module 'svelte/types/compiler/preprocess' {

0 commit comments

Comments
 (0)