Event Target Shim is a polyfill implementation of the WHATWG EventTarget and Event interfaces, designed to work seamlessly across both browser and Node.js environments. It provides full compatibility with modern EventTarget standards including constructor support, passive event listeners, once-only listeners, and AbortSignal integration for listener cleanup.
npm install event-target-shimimport { EventTarget, Event } from "event-target-shim";For CommonJS:
const { EventTarget, Event } = require("event-target-shim");For ES5 legacy browser support:
import { EventTarget, Event } from "event-target-shim/es5";For UMD (browser globals):
<script src="node_modules/event-target-shim/umd.js"></script>
<!-- Exposes global EventTargetShim -->import { EventTarget, Event } from "event-target-shim";
// Create an EventTarget instance
const target = new EventTarget();
// Add event listener with modern options
target.addEventListener("test", (event) => {
console.log("Event received:", event.type);
}, {
once: true, // Remove after first call
passive: true // Cannot preventDefault
});
// Create and dispatch event
const event = new Event("test", { bubbles: true });
target.dispatchEvent(event);
// Use AbortSignal for cleanup
const controller = new AbortController();
target.addEventListener("cleanup", handler, {
signal: controller.signal
});
controller.abort(); // Removes the listenerEvent Target Shim provides two core classes that implement the WHATWG specifications:
The main EventTarget implementation with full WHATWG compatibility and TypeScript generics for type safety.
/**
* An implementation of the EventTarget interface
*/
class EventTarget<TEventMap extends Record<string, Event> = Record<string, Event>, TMode extends "standard" | "strict" = "standard"> {
/**
* Initialize EventTarget instance
*/
constructor();
/**
* Add an event listener with modern options support
* @param type - Event type string
* @param callback - Event listener function or object
* @param options - Listener options (passive, once, signal, capture)
*/
addEventListener<T extends string & keyof TEventMap>(
type: T,
callback?: EventTarget.EventListener<this, TEventMap[T]> | null,
options?: EventTarget.AddOptions
): void;
addEventListener(
type: string,
callback?: EventTarget.FallbackEventListener<this, TMode>,
options?: EventTarget.AddOptions
): void;
/**
* Add event listener with legacy boolean capture flag (deprecated)
* @param type - Event type string
* @param callback - Event listener function
* @param capture - Capture phase flag
* @deprecated Use options object instead
*/
addEventListener<T extends string & keyof TEventMap>(
type: T,
callback: EventTarget.EventListener<this, TEventMap[T]> | null | undefined,
capture: boolean
): void;
/**
* Remove an event listener
* @param type - Event type string
* @param callback - Event listener to remove
* @param options - Listener options (capture)
*/
removeEventListener<T extends string & keyof TEventMap>(
type: T,
callback?: EventTarget.EventListener<this, TEventMap[T]> | null,
options?: EventTarget.Options
): void;
removeEventListener(
type: string,
callback?: EventTarget.FallbackEventListener<this, TMode>,
options?: EventTarget.Options
): void;
/**
* Remove event listener with legacy boolean capture flag (deprecated)
* @param type - Event type string
* @param callback - Event listener to remove
* @param capture - Capture phase flag
* @deprecated Use options object instead
*/
removeEventListener<T extends string & keyof TEventMap>(
type: T,
callback: EventTarget.EventListener<this, TEventMap[T]> | null | undefined,
capture: boolean
): void;
/**
* Dispatch an event to all registered listeners
* @param event - Event object to dispatch
* @returns true if event was not cancelled, false otherwise
*/
dispatchEvent<T extends string & keyof TEventMap>(
event: EventTarget.EventData<TEventMap, TMode, T>
): boolean;
dispatchEvent(event: EventTarget.FallbackEvent<TMode>): boolean;
}WHATWG Event interface implementation with all standard properties and methods.
/**
* An implementation of Event interface that wraps event objects
*/
class Event<TEventType extends string = string> {
/**
* Event phase constants
*/
static get NONE(): number; // 0
static get CAPTURING_PHASE(): number; // 1
static get AT_TARGET(): number; // 2
static get BUBBLING_PHASE(): number; // 3
/**
* Initialize Event instance
* @param type - Event type string
* @param eventInitDict - Event initialization options
*/
constructor(type: TEventType, eventInitDict?: Event.EventInit);
/**
* Event type string
*/
get type(): TEventType;
/**
* Event target (the object that dispatched the event)
*/
get target(): EventTarget | null;
/**
* Legacy alias for target property (deprecated)
* @deprecated Use target instead
*/
get srcElement(): EventTarget | null;
/**
* Current event target (the object currently handling the event)
*/
get currentTarget(): EventTarget | null;
/**
* Current event phase (0-3)
*/
get eventPhase(): number;
/**
* Whether event bubbles up the DOM tree
*/
get bubbles(): boolean;
/**
* Whether event can be cancelled
*/
get cancelable(): boolean;
/**
* Whether default behavior was prevented
*/
get defaultPrevented(): boolean;
/**
* Whether event crosses shadow DOM boundaries
*/
get composed(): boolean;
/**
* Whether event was dispatched by user agent
*/
get isTrusted(): boolean;
/**
* Time when event was created (milliseconds)
*/
get timeStamp(): number;
/**
* Legacy bubble control property (deprecated)
* @deprecated Use stopPropagation() instead
*/
get cancelBubble(): boolean;
set cancelBubble(value: boolean);
/**
* Legacy default prevention property (deprecated)
* @deprecated Use preventDefault() instead
*/
get returnValue(): boolean;
set returnValue(value: boolean);
/**
* Instance event phase constants
*/
get NONE(): number;
get CAPTURING_PHASE(): number;
get AT_TARGET(): number;
get BUBBLING_PHASE(): number;
/**
* Get event path (simplified - returns current target only)
* @returns Array containing current target
*/
composedPath(): EventTarget[];
/**
* Stop event propagation to remaining listeners
*/
stopPropagation(): void;
/**
* Stop event propagation and cancel remaining listeners on current target
*/
stopImmediatePropagation(): void;
/**
* Prevent default behavior if event is cancelable
*/
preventDefault(): void;
/**
* Legacy event initialization method (deprecated)
* @param type - Event type
* @param bubbles - Whether event bubbles
* @param cancelable - Whether event is cancelable
* @deprecated Constructor handles initialization
*/
initEvent(type: string, bubbles?: boolean, cancelable?: boolean): void;
}Global error handler for unhandled errors during event listener execution.
/**
* Set global error handler for event listener errors
* @param value - Error handler function or undefined to unset
*/
function setErrorHandler(value: setErrorHandler.ErrorHandler | undefined): void;
/**
* Error handler function type
* @param error - The error that occurred
*/
type ErrorHandler = (error: Error) => void;Usage Example:
import { setErrorHandler } from "event-target-shim";
setErrorHandler((error) => {
console.error("Event listener error:", error);
// Send to error reporting service
});Global warning handler for deprecated API usage and other warnings.
/**
* Set global warning handler
* @param value - Warning handler function or undefined to unset
*/
function setWarningHandler(value: setWarningHandler.WarningHandler | undefined): void;
/**
* Warning handler function type
* @param warning - The warning information
*/
type WarningHandler = (warning: setWarningHandler.Warning) => void;
/**
* Warning information structure
*/
interface Warning {
/** Warning code identifier */
code: string;
/** Human-readable warning message */
message: string;
/** Arguments for message placeholders */
args: any[];
}Utility functions for working with event attributes (on* properties) on EventTarget objects.
/**
* Get current value of an event attribute
* @param target - EventTarget to query
* @param type - Event type name
* @returns Current event listener function or null
*/
function getEventAttributeValue<TEventTarget extends EventTarget<any, any>, TEvent extends Event>(
target: TEventTarget,
type: string
): EventTarget.CallbackFunction<TEventTarget, TEvent> | null;
/**
* Set event listener for an event attribute
* @param target - EventTarget to modify
* @param type - Event type name
* @param callback - Event listener function or null
*/
function setEventAttributeValue(
target: EventTarget<any, any>,
type: string,
callback: EventTarget.CallbackFunction<any, any> | null
): void;Usage Example:
import { EventTarget, getEventAttributeValue, setEventAttributeValue } from "event-target-shim";
const target = new EventTarget();
// Set onclick handler
setEventAttributeValue(target, "click", (event) => {
console.log("Clicked!");
});
// Get current handler
const handler = getEventAttributeValue(target, "click");
console.log(handler); // Function or nullFunctions for creating EventTarget classes with predefined event attributes. These are deprecated in favor of the get/set attribute value functions.
/**
* Create EventTarget subclass with predefined event attributes (deprecated)
* @param types - Event type names to create on* properties for
* @returns Constructor for custom EventTarget class
* @deprecated Use getEventAttributeValue/setEventAttributeValue instead
*/
function defineCustomEventTarget<TEventMap extends Record<string, Event>, TMode extends "standard" | "strict" = "standard">(
...types: (string & keyof TEventMap)[]
): defineCustomEventTarget.CustomEventTargetConstructor<TEventMap, TMode>;
/**
* Define single event attribute on EventTarget instance (deprecated)
* @param target - EventTarget to modify
* @param type - Event type name
* @param eventClass - Event constructor (for type inference)
* @deprecated Use getEventAttributeValue/setEventAttributeValue instead
*/
function defineEventAttribute<TEventTarget extends EventTarget, TEventType extends string, TEventConstructor extends typeof Event>(
target: TEventTarget,
type: TEventType,
eventClass?: TEventConstructor
): void;/**
* Event listener options for addEventListener
*/
interface AddOptions extends Options {
/** Listener cannot call preventDefault */
passive?: boolean;
/** Remove listener after first invocation */
once?: boolean;
/** AbortSignal to remove listener when aborted */
signal?: AbortSignal | null | undefined;
}
/**
* Event listener options for removeEventListener
*/
interface Options {
/** Listen during capture phase */
capture?: boolean;
}
/**
* Event listener function type
*/
interface CallbackFunction<TEventTarget extends EventTarget<any, any>, TEvent extends Event> {
(this: TEventTarget, event: TEvent): void;
}
/**
* Event listener object type
*/
interface CallbackObject<TEvent extends Event> {
handleEvent(event: TEvent): void;
}
/**
* Event listener union type (function or object)
*/
type EventListener<TEventTarget extends EventTarget<any, any>, TEvent extends Event> =
CallbackFunction<TEventTarget, TEvent> | CallbackObject<TEvent>;
/**
* AbortSignal interface for listener cleanup
*/
interface AbortSignal extends EventTarget<{ abort: Event }> {
readonly aborted: boolean;
onabort: CallbackFunction<AbortSignal, Event> | null;
}/**
* Event initialization options
*/
interface EventInit {
/** Whether event bubbles */
bubbles?: boolean;
/** Whether event is cancelable */
cancelable?: boolean;
/** Whether event is composed (crosses shadow boundaries) */
composed?: boolean;
}/**
* Error handler for setErrorHandler
*/
type ErrorHandler = (error: Error) => void;
/**
* Warning handler for setWarningHandler
*/
type WarningHandler = (warning: Warning) => void;
/**
* Warning information structure
*/
interface Warning {
code: string;
message: string;
args: any[];
}