Skip to content

Instantly share code, notes, and snippets.

@enyo
Created October 8, 2022 15:45
Show Gist options
  • Save enyo/df55d134db0f7f5a48182da58b419d3e to your computer and use it in GitHub Desktop.
Save enyo/df55d134db0f7f5a48182da58b419d3e to your computer and use it in GitHub Desktop.
TypeScript TypedEventTarget
/**
* Implements the EventTarget, but with type safety.
*
* Extend this class with an object that describes your events like this:
*
* type AccountEvents = {
* logout: null
* 'sign-in': { username: string; password: string }
* }
* class Account extends TypedEventTarget<AccountEvents> {
* // Your class implementationt
* }
*
* const user = new Account()
*
* // Both the event `sign-in` and the `event.detail` object are typed and auto-
* // completed now.
* user.addEventListener('sign-in', event => {
* event.detail.username
* })
*/
export class TypedEventTarget<
EventDef extends { [key: string]: unknown },
> extends EventTarget {
public dispatch<
T extends Extract<keyof EventDef, string>,
E extends EventDef[T],
>(type: T, e: E): boolean {
const event = new CustomEvent(type, { detail: e })
return super.dispatchEvent(event)
}
public override addEventListener<
T extends Extract<keyof EventDef, string>,
E extends CustomEvent<EventDef[T]>,
>(
type: T,
listener:
| ((e: E) => void)
| {
handleEvent(object: E): void
}
| null,
) {
super.addEventListener(type, listener as EventListenerOrEventListenerObject)
}
public override removeEventListener(type: Extract<keyof EventDef, string>) {
super.removeEventListener(type, null)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment