Skip to content

Instantly share code, notes, and snippets.

@reosablo
Last active May 21, 2024 11:27
Show Gist options
  • Select an option

  • Save reosablo/f30acf6d1b1cd36eebcc38410c9220e9 to your computer and use it in GitHub Desktop.

Select an option

Save reosablo/f30acf6d1b1cd36eebcc38410c9220e9 to your computer and use it in GitHub Desktop.
Pure typed `EventTarget` derivation without any dependencies nor overhead on runtime
/**
* @file Pure Typed EventTarget
* @license Unlicense
*/
export declare class TypedEventTarget<EventMap extends Record<string, Event>>
extends EventTarget {
addEventListener<Type extends keyof EventMap>(
type: Type,
listener: (this: this, evt: EventMap[Type]) => void,
options?: boolean | AddEventListenerOptions
): void;
addEventListener(
...args: Parameters<EventTarget["addEventListener"]>
): void;
removeEventListener<Type extends keyof EventMap>(
type: Type,
listener: (this: this, evt: EventMap[Type]) => void,
options?: boolean | EventListenerOptions
): void;
removeEventListener(
...args: Parameters<EventTarget["removeEventListener"]>
): void;
}
import type { TypedEventTarget } "./typed-event-target.ts";
// TypeScript 4.7+
class Foo extends (EventTarget as typeof TypedEventTarget<{
foo: CustomEvent<string>;
bar: CustomEvent<number>;
baz: CustomEvent<{ ok: boolean }>;
}>) { }
// TypeScript 4.6
class Bar extends (EventTarget as {
new (): TypedEventTarget<{
foo: CustomEvent<string>;
bar: CustomEvent<number>;
baz: CustomEvent<{ ok: boolean }>;
}>
}) { }
// ^ compiled JavaScript code:
// class Foo extends EventTarget { }
// class Bar extends EventTarget { }
new Foo().addEventListener("baz", (event) => {
// ^^^^^ auto complete available: "foo", "bar" or "baz"
event.detail;
// ^^^^^^ infered as { ok: boolean }
});
@reosablo
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment