typescript-event-target
A strictly typed drop-in replacement for EventTarget with full TypeScript event-map inference.
Repository Health
Technical Analysis
typescript-event-target provides TypedEventTarget, a class that directly extends the native EventTarget so it works as a drop-in replacement anywhere an EventTarget is expected. By pairing it with a user-defined interface mapping event names to their Event subclasses, addEventListener and removeEventListener gain full type inference — the listener callback is typed to the exact event class for that event name, and unknown event names are rejected at compile time.
The package also introduces dispatchTypedEvent, a type-safe alternative to the deprecated-in-this-context dispatchEvent, which requires the event type as an explicit generic parameter so a mismatched event class is caught by the compiler rather than at runtime. Because the implementation is almost entirely type declarations plus one small wrapper method, it adds close to zero bytes to a production bundle, and is published to npm, JSR, and deno.land/x for use across Node.js, Deno, and browser environments.
What You Get
- A
TypedEventTarget<M>class that extendsEventTargetdirectly, so instances passinstanceof EventTargetchecks and work with existing EventTarget-based APIs - Type-checked
addEventListener/removeEventListenercalls where the listener’s event parameter is inferred from the event map interface - A
dispatchTypedEvent(type, event)method that enforces the dispatched event’s class matches the type declared for that event name - Compile-time errors for unknown event names, mismatched event types, and event map entries that don’t extend
Event - Near-zero runtime footprint — only a thin dispatch wrapper is compiled, with the rest resolved purely at the type level
Common Use Cases
- Building custom UI widgets or web components that emit strongly typed custom events instead of untyped
CustomEvent<any> - Wrapping WebSocket, Worker, or other message-based APIs in an EventTarget-based interface with autocomplete for event names and payload types
- Implementing small pub-sub state containers or stores on top of EventTarget with type-safe change/update events
- Migrating code from Node’s
EventEmitterto the standardEventTargetwhile retaining familiar type-safety guarantees
Under The Hood
Architecture
typescript-event-target is a single-purpose type-level wrapper: src/TypedEventTarget.ts declares both an interface and a class of the same name — the interface narrows the inherited addEventListener/removeEventListener/dispatchEvent signatures using TypeScript’s generic constraint M extends ValueIsEvent<M>, while the class itself extends the native EventTarget and adds a single new method, dispatchTypedEvent, which simply calls super.dispatchEvent(event) after the caller has supplied the type parameter for compile-time checking. There is no internal state, no event bus, and no abstraction beyond this — the entire library exists to reshape TypeScript’s view of the browser-native EventTarget API without altering its runtime behavior at all.
Tech Stack
The project is pure TypeScript with a minimal toolchain: tsup builds CJS and ESM bundles with .d.ts output directly from src/index.ts, tsd runs the type-only test suite, and eslint/eslint-config-prettier/prettier handle linting and formatting. There are zero runtime dependencies — package.json lists only devDependencies — and the package is additionally published to JSR and deno.land/x alongside npm, so the same source targets three distribution channels without any bundler-specific code paths.
Code Quality
Testing is entirely type-level: test-d/TypedEventTarget.test-d.ts uses tsd’s expectType and @ts-expect-error assertions to verify that listener callbacks infer the correct event subclass, that unknown event names and mismatched dispatch calls fail to compile, and that dispatchEvent is marked @deprecated. There are no runtime unit tests, which is appropriate given the library has almost no runtime logic to test. Source files are small, single-purpose, and thoroughly documented with TSDoc comments describing each method’s behavior, and CI-style checks (lint, test, build) are defined as npm scripts with a documented contribution workflow.
What Makes It Unique
Rather than building a new event-emitter abstraction, the library’s contribution is narrowly and precisely scoped: making the standard, browser-native EventTarget fully type-safe while remaining a true drop-in replacement, including for existing code paths that already call dispatchEvent directly. That combination — zero added runtime behavior, full backward compatibility with EventTarget-typed code, and strict generic inference for both listening and dispatching — is uncommon among typed event-emitter alternatives, most of which introduce their own emitter class instead of extending the platform API.