|
| 1 | +# typed-event-utils |
| 2 | + |
| 3 | + |
| 4 | + |
| 5 | + |
| 6 | +A collection of type-safe utilities for working with events. |
| 7 | + |
| 8 | +## Features |
| 9 | + |
| 10 | +- **Type-safe Event**: Strongly typed Event constructor with enhanced type safety |
| 11 | +- **Type-safe EventTarget**: Strongly typed event handling with full TypeScript support |
| 12 | +- **AbortableEventTarget**: EventTarget with built-in abort functionality for automatic cleanup |
| 13 | + |
| 14 | +## Installation |
| 15 | + |
| 16 | +```shell |
| 17 | +npm install typed-event-utils |
| 18 | +``` |
| 19 | + |
| 20 | +## Usage |
| 21 | + |
| 22 | +### Event |
| 23 | + |
| 24 | +The `Event` constructor provides type safety for event creation with enhanced target typing. |
| 25 | + |
| 26 | +```typescript |
| 27 | +import { Event } from "typed-event-utils/event" |
| 28 | + |
| 29 | +// create a typed event with target type information |
| 30 | +const event = new Event<HTMLButtonElement>("click") |
| 31 | + |
| 32 | +// the event has properly typed currentTarget and target properties |
| 33 | +// event.currentTarget: HTMLButtonElement |
| 34 | +// event.target: HTMLButtonElement |
| 35 | +``` |
| 36 | + |
| 37 | +### EventTarget |
| 38 | + |
| 39 | +The `EventTarget` class provides type safety for event handling. |
| 40 | + |
| 41 | +```typescript |
| 42 | +import { EventTarget } from "typed-event-utils" |
| 43 | + |
| 44 | +// define your event types |
| 45 | +type Events = { |
| 46 | + "success": CustomEvent<{ message: string }> |
| 47 | + "error": ErrorEvent |
| 48 | +} |
| 49 | + |
| 50 | +// create a typed event target |
| 51 | +const target = new EventTarget<Events>() |
| 52 | + |
| 53 | +// add event listeners with full type safety |
| 54 | +target.addEventListener("success", (event) => { |
| 55 | + // event.detail is properly typed with { message: string } |
| 56 | + console.log("success message:", event.detail.message) |
| 57 | +}) |
| 58 | + |
| 59 | +target.addEventListener("error", (event) => { |
| 60 | + // event is properly typed as an ErrorEvent |
| 61 | + console.log(event.message) |
| 62 | +}) |
| 63 | + |
| 64 | +// dispatch an error event |
| 65 | +target.dispatchEvent(new ErrorEvent("error", { message: "cause" })) |
| 66 | + |
| 67 | +// @ts-expect-error because "invalid" is not an allowable event |
| 68 | +target.addEventListener("invalid", (event) => {}) |
| 69 | + |
| 70 | +// @ts-expect-error because MessageEvent is not an allowable instance |
| 71 | +target.dispatchEvent(new MessageEvent("error", { message: "cause" })) |
| 72 | +``` |
| 73 | + |
| 74 | +### AbortableEventTarget |
| 75 | + |
| 76 | +The `AbortableEventTarget` class extends `EventTarget` to support cleanup capabilities. |
| 77 | + |
| 78 | +```typescript |
| 79 | +import { AbortableEventTarget } from "typed-event-utils/abortable-event-target" |
| 80 | + |
| 81 | +type Events = { |
| 82 | + "update-data": CustomEvent<{ data: any }> |
| 83 | +} |
| 84 | + |
| 85 | +const target = new AbortableEventTarget<Events>() |
| 86 | + |
| 87 | +// All listeners are automatically connected to an AbortSignal associated with the target |
| 88 | +target.addEventListener("update-data", (event) => { |
| 89 | + console.log("Data updated:", event.detail.data) |
| 90 | +}) |
| 91 | + |
| 92 | +// Remove all listeners at once |
| 93 | +target.abort() |
| 94 | + |
| 95 | +// The AbortSignal is accessible if needed |
| 96 | +console.log(target.signal.aborted) // true after abort() |
| 97 | +``` |
| 98 | + |
| 99 | +## API Reference |
| 100 | + |
| 101 | +### Event\<T, U\> |
| 102 | + |
| 103 | +A generic `Event` constructor that provides type safety for event creation with enhanced target typing. |
| 104 | + |
| 105 | +- `new Event<T, U>(type, eventInitDict?)`: Creates a typed event with target type information. |
| 106 | + |
| 107 | +### EventTarget\<T\> |
| 108 | + |
| 109 | +A generic `EventTarget` that provides type safety for event handling. |
| 110 | + |
| 111 | +- `new EventTarget<T>()`: Creates a typed event target with typed events. |
| 112 | + |
| 113 | +#### Methods |
| 114 | + |
| 115 | +- `addEventListener(type, listener, options?)`: Adds a typed event listener. |
| 116 | +- `removeEventListener(type, listener, options?)`: Removes a typed event listener. |
| 117 | +- `dispatchEvent(event)`: Dispatches a typed event. |
| 118 | + |
| 119 | +### AbortableEventTarget\<T\> |
| 120 | + |
| 121 | +Extends `EventTarget` with automatic cleanup capabilities. |
| 122 | + |
| 123 | +- `new EventTarget<T>()`: Creates a typed event target with typed events and cleanup capabilities. |
| 124 | + |
| 125 | +#### Methods |
| 126 | + |
| 127 | +Extends `EventTarget` methods. |
| 128 | + |
| 129 | +- `abort(reason?)`: Aborts all event listeners on the target. |
| 130 | + |
| 131 | +#### Properties |
| 132 | + |
| 133 | +- `signal`: Read-only `AbortSignal` for the event target. |
| 134 | + |
| 135 | +<br /> |
| 136 | + |
| 137 | +## License |
| 138 | + |
| 139 | +### MIT No Attribution |
| 140 | + |
| 141 | +#### Copyright 2025 Jonathan Neal |
| 142 | + |
| 143 | +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so. |
| 144 | + |
| 145 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
0 commit comments