Socket
Socket
Sign inDemoInstall

event-target-shim

Package Overview
Dependencies
0
Maintainers
1
Versions
27
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 4.0.3 to 5.0.0-beta.0

358

index.d.ts

@@ -1,3 +0,7 @@

export as namespace EventTargetShim;
export as namespace EventTargetShim
/**
* `Event` interface.
* @see https://dom.spec.whatwg.org/#event
*/
export interface Event {

@@ -7,3 +11,3 @@ /**

*/
readonly type: string;
readonly type: string

@@ -13,3 +17,3 @@ /**

*/
readonly target: EventTarget | null;
readonly target: EventTarget<{}, {}, "standard"> | null

@@ -19,8 +23,9 @@ /**

*/
readonly currentTarget: EventTarget | null;
readonly currentTarget: EventTarget<{}, {}, "standard"> | null
/**
* The target of this event.
* @deprecated
*/
readonly srcElement: any | null;
readonly srcElement: any | null

@@ -30,3 +35,3 @@ /**

*/
composedPath(): EventTarget[];
composedPath(): EventTarget<{}, {}, "standard">[]

@@ -36,3 +41,3 @@ /**

*/
readonly NONE: number;
readonly NONE: number

@@ -42,3 +47,3 @@ /**

*/
readonly CAPTURING_PHASE: number;
readonly CAPTURING_PHASE: number

@@ -48,3 +53,3 @@ /**

*/
readonly BUBBLING_PHASE: number;
readonly BUBBLING_PHASE: number

@@ -54,3 +59,3 @@ /**

*/
readonly AT_TARGET: number;
readonly AT_TARGET: number

@@ -60,3 +65,3 @@ /**

*/
readonly eventPhase: number;
readonly eventPhase: number

@@ -66,3 +71,3 @@ /**

*/
stopPropagation(): void;
stopPropagation(): void

@@ -72,3 +77,3 @@ /**

*/
stopImmediatePropagation(): void;
stopImmediatePropagation(): void

@@ -79,3 +84,3 @@ /**

*/
initEvent(type: string, bubbles?: boolean, cancelable?: boolean): void;
initEvent(type: string, bubbles?: boolean, cancelable?: boolean): void

@@ -85,13 +90,15 @@ /**

*/
readonly bubbles: boolean;
readonly bubbles: boolean
/**
* Stop event bubbling.
* @deprecated
*/
cancelBubble: boolean;
cancelBubble: boolean
/**
* Set or get cancellation flag.
* @deprecated
*/
returnValue: boolean;
returnValue: boolean

@@ -101,3 +108,3 @@ /**

*/
readonly cancelable: boolean;
readonly cancelable: boolean

@@ -107,3 +114,3 @@ /**

*/
preventDefault(): void;
preventDefault(): void

@@ -113,3 +120,3 @@ /**

*/
readonly defaultPrevented: boolean;
readonly defaultPrevented: boolean

@@ -119,3 +126,3 @@ /**

*/
readonly composed: boolean;
readonly composed: boolean

@@ -125,3 +132,3 @@ /**

*/
readonly isTrusted: boolean;
readonly isTrusted: boolean

@@ -131,22 +138,26 @@ /**

*/
readonly timeStamp: number;
readonly timeStamp: number
}
export interface EventListenerOptions {
capture?: boolean;
/**
* The constructor of `EventTarget` interface.
*/
export type EventTargetConstructor<
TEvents extends EventTarget.EventDefinition = {},
TEventAttributes extends EventTarget.EventDefinition = {},
TMode extends EventTarget.Mode = "loose"
> = {
prototype: EventTarget<TEvents, TEventAttributes, TMode>
new(): EventTarget<TEvents, TEventAttributes, TMode>
}
export interface AddEventListenerOptions extends EventListenerOptions {
passive?: boolean;
once?: boolean;
}
export type EventTargetListener = ((event: Event) => void) | { handleEvent(event: Event): void };
export interface PartialEvent extends Partial<Event> {
type: string;
[key: string]: any;
}
export interface EventTarget {
/**
* `EventTarget` interface.
* @see https://dom.spec.whatwg.org/#interface-eventtarget
*/
export type EventTarget<
TEvents extends EventTarget.EventDefinition = {},
TEventAttributes extends EventTarget.EventDefinition = {},
TMode extends EventTarget.Mode = "loose"
> = EventTarget.EventAttributes<TEventAttributes> & {
/**

@@ -158,7 +169,9 @@ * Add a given listener to this event target.

*/
addEventListener(
eventName: string,
listener: EventTargetListener | null,
options?: boolean | AddEventListenerOptions,
): void;
addEventListener<TEventType extends EventTarget.EventType<TEvents, TMode>>(
type: TEventType,
listener:
| EventTarget.Listener<EventTarget.PickEvent<TEvents, TEventType>>
| null,
options?: boolean | EventTarget.AddOptions
): void

@@ -171,7 +184,9 @@ /**

*/
removeEventListener(
eventName: string,
listener: EventTargetListener | null,
options?: boolean | EventListenerOptions,
): void;
removeEventListener<TEventType extends EventTarget.EventType<TEvents, TMode>>(
type: TEventType,
listener:
| EventTarget.Listener<EventTarget.PickEvent<TEvents, TEventType>>
| null,
options?: boolean | EventTarget.RemoveOptions
): void

@@ -183,40 +198,235 @@ /**

*/
dispatchEvent(event: PartialEvent): boolean;
dispatchEvent<TEventType extends EventTarget.EventType<TEvents, TMode>>(
event: EventTarget.EventData<TEvents, TEventType, TMode>
): boolean
}
type EventAttributes<T extends string> = {
[K in T]: ((ev: Event) => void) | null;
};
export const EventTarget: EventTargetConstructor & {
/**
* Create an `EventTarget` instance with detailed event definition.
*
* The detailed event definition requires to use `defineEventAttribute()`
* function later.
*
* Unfortunately, the second type parameter `TEventAttributes` was needed
* because we cannot compute string literal types.
*
* @example
* const signal = new EventTarget<{ abort: Event }, { onabort: Event }>()
* defineEventAttribute(signal, "abort")
*/
new <
TEvents extends EventTarget.EventDefinition,
TEventAttributes extends EventTarget.EventDefinition,
TMode extends EventTarget.Mode = "loose"
>(): EventTarget<TEvents, TEventAttributes, TMode>
type EventTargetConstructor = {
prototype: EventTarget;
new(): EventTarget;
};
/**
* Define an `EventTarget` constructor with attribute events.
* @param events Event types to define attribute events (e.g. passing in `"click"` adds `onclick` to prototype).
*/
(events: string[]): EventTargetConstructor
/**
* Define an `EventTarget` constructor with attribute events.
* @param events Event types to define attribute events (e.g. passing in `"click"` adds `onclick` to prototype).
*/
(...events: string[]): EventTargetConstructor
type ExEventTarget<T extends string> = EventTarget & EventAttributes<T>;
/**
* Define an `EventTarget` constructor with attribute events and detailed event definition.
*
* Unfortunately, the second type parameter `TEventAttributes` was needed
* because we cannot compute string literal types.
*
* @example
* class AbortSignal extends EventTarget<{ abort: Event }, { onabort: Event }>("abort") {
* abort(): void {}
* }
*
* @param events Optional event attributes (e.g. passing in `"click"` adds `onclick` to prototype).
*/
<
TEvents extends EventTarget.EventDefinition,
TEventAttributes extends EventTarget.EventDefinition,
TMode extends EventTarget.Mode = "loose"
>(events: (keyof TEvents)[]): EventTargetConstructor<
TEvents,
TEventAttributes,
TMode
>
type ExEventTargetConstructor<T extends string> = {
prototype: ExEventTarget<T>;
new(): ExEventTarget<T>;
};
export const EventTarget: {
new(): EventTarget;
new<T extends string>(): ExEventTarget<T>;
/**
* The event target wrapper to be used when extending objects.
* Define an `EventTarget` constructor with attribute events and detailed event definition.
*
* Unfortunately, the second type parameter `TEventAttributes` was needed
* because we cannot compute string literal types.
*
* @example
* class AbortSignal extends EventTarget<{ abort: Event }, { onabort: Event }>("abort") {
* abort(): void {}
* }
*
* @param events Optional event attributes (e.g. passing in `"click"` adds `onclick` to prototype).
*/
(events: string[]): EventTargetConstructor;
(...events: string[]): EventTargetConstructor;
<T extends string>(events: string[]): ExEventTargetConstructor<T>;
<T extends string>(...events: string[]): ExEventTargetConstructor<T>;
};
export default EventTarget;
<
TEvents extends EventTarget.EventDefinition,
TEventAttributes extends EventTarget.EventDefinition,
TMode extends EventTarget.Mode = "loose"
>(...events: (keyof TEvents)[]): EventTargetConstructor<
TEvents,
TEventAttributes,
TMode
>
}
export namespace EventTarget {
/**
* Options of `removeEventListener()` method.
*/
export interface RemoveOptions {
/**
* The flag to indicate that the listener is for the capturing phase.
*/
capture?: boolean
}
/**
* Options of `addEventListener()` method.
*/
export interface AddOptions extends RemoveOptions {
/**
* The flag to indicate that the listener doesn't support
* `event.preventDefault()` operation.
*/
passive?: boolean
/**
* The flag to indicate that the listener will be removed on the first
* event.
*/
once?: boolean
}
/**
* The type of regular listeners.
*/
export interface FunctionListener<TEvent> {
(event: TEvent): void
}
/**
* The type of object listeners.
*/
export interface ObjectListener<TEvent> {
handleEvent(event: TEvent): void
}
/**
* The type of listeners.
*/
export type Listener<TEvent = Event> =
| FunctionListener<TEvent>
| ObjectListener<TEvent>
/**
* Event definition.
*/
export type EventDefinition = {
readonly [key: string]: Event
}
/**
* Mapped type for event attributes.
*/
export type EventAttributes<TEventAttributes extends EventDefinition> = {
[P in keyof TEventAttributes]:
| FunctionListener<TEventAttributes[P]>
| null
}
/**
* The type of event data for `dispatchEvent()` method.
*/
export type EventData<
TEvents extends EventDefinition,
TEventType extends keyof TEvents | string,
TMode extends Mode
> =
TEventType extends keyof TEvents
? (
// Require properties which are not generated automatically.
& Pick<
TEvents[TEventType],
Exclude<keyof TEvents[TEventType], OmittableEventKeys>
>
// Properties which are generated automatically are optional.
& Partial<Pick<Event, OmittableEventKeys>>
)
: (
TMode extends "standard"
? Event
: Event | NonStandardEvent
)
/**
* The string literal types of the properties which are generated
* automatically in `dispatchEvent()` method.
*/
export type OmittableEventKeys = Exclude<keyof Event, "type">
/**
* The type of event data.
*/
export type NonStandardEvent = {
[key: string]: any
type: string
}
/**
* The type of listeners.
*/
export type PickEvent<
TEvents extends EventDefinition,
TEventType extends keyof TEvents | string,
> =
TEventType extends keyof TEvents
? TEvents[TEventType]
: Event
/**
* Event type candidates.
*/
export type EventType<
TEvents extends EventDefinition,
TMode extends Mode
> =
TMode extends "strict"
? keyof TEvents
: keyof TEvents | string
/**
* - `"strict"` ..... Methods don't accept unknown events.
* `dispatchEvent()` accepts partial objects.
* - `"loose"` ...... Methods accept unknown events.
* `dispatchEvent()` accepts partial objects.
* - `"standard"` ... Methods accept unknown events.
* `dispatchEvent()` doesn't accept partial objects.
*/
export type Mode = "strict" | "standard" | "loose"
}
/**
* Specialized `type` property.
*/
export type Type<T extends string> = { type: T }
/**
* Define an event attribute (e.g. `eventTarget.onclick`).
* @param eventTargetPrototype The event target prototype to define an event attribute.
* @param prototype The event target prototype to define an event attribute.
* @param eventName The event name to define.
*/
export function defineEventAttribute(eventTargetPrototype: EventTarget, eventName: string): void;
export function defineEventAttribute(
prototype: EventTarget,
eventName: string
): void
export default EventTarget
{
"name": "event-target-shim",
"version": "4.0.3",
"version": "5.0.0-beta.0",
"description": "An implementation of WHATWG EventTarget interface.",

@@ -24,7 +24,6 @@ "main": "dist/event-target-shim",

"test": "run-s test:*",
"test:mocha": "nyc --require ./scripts/babel-register mocha test/index.mjs",
"test:mocha": "nyc --require ./scripts/babel-register mocha test/*.mjs",
"test:karma": "karma start scripts/karma.conf.js --single-run",
"test:types": "tsc",
"watch": "run-p watch:*",
"watch:mocha": "mocha test/index.mjs --require ./scripts/babel-register --watch --watch-extensions js,mjs --growl",
"watch:mocha": "mocha test/*.mjs --require ./scripts/babel-register --watch --watch-extensions js,mjs --growl",
"watch:karma": "karma start scripts/karma.conf.js --watch",

@@ -31,0 +30,0 @@ "codecov": "codecov"

@@ -154,14 +154,18 @@ # event-target-shim

Currently typescript does not support type mutation by method, therefore the previous example will **not work** without the following modifications:
#### Working example #1
```ts
import { EventTarget, defineEventAttribute } from "event-target-shim";
// Define events
type FooEvents = {
hello: CustomEvent
}
type FooEventAttributes = {
onhello: CustomEvent
}
// Define a derived class.
class Foo extends EventTarget<"onhello"> {
class Foo extends EventTarget<FooEvents, FooEventAttributes> {
// ...
}
// Define `foo.onhello` property.
// Define `foo.onhello` property's implementation.
defineEventAttribute(Foo.prototype, "hello")

@@ -172,6 +176,6 @@

foo.addEventListener("hello", (e) => {
console.log("hello", e)
console.log("hello", e.detail)
})
foo.onhello = (e) => {
console.log("onhello", e)
console.log("onhello", e.detail)
}

@@ -183,24 +187,46 @@

In the future, if typescript adds support to string literal mutation (joining, slicing and etc.), it should be possible to automatically infer `onhello` type from `hello`. However, until then you are stuck with this:
Unfortunately, both `FooEvents` and `FooEventAttributes` are needed because TypeScript doesn't allow the mutation of string literal types. If TypeScript allowed us to compute `"onhello"` from `"hello"` in types, `FooEventAttributes` will be optional.
#### Working example #2
This `EventTarget` type is compatible with `EventTarget` interface of `lib.dom.d.ts`.
#### To disallow unknown events
By default, methods such as `addEventListener` accept unknown events. You can disallow unknown events by the third type parameter `"strict"`.
```ts
import { EventTarget, defineEventAttribute } from "event-target-shim";
// Define a derived class.
class Foo extends EventTarget<"onhello">("hello") {
type FooEvents = {
hello: CustomEvent
}
class Foo extends EventTarget<FooEvents, {}, "strict"> {
// ...
}
// Register event listeners.
const foo = new Foo()
// OK because `hello` is defined in FooEvents.
foo.addEventListener("hello", (e) => {
console.log("hello", e)
})
foo.onhello = (e) => {
console.log("onhello", e)
// Error because `unknown` is not defined in FooEvents.
foo.addEventListener("unknown", (e) => {
})
```
However, if you use `"strict"` parameter, it loses compatibility with `EventTarget` interface of `lib.dom.d.ts`.
#### To infer the type of `dispatchEvent()` method
TypeScript cannot infer the event type of `dispatchEvent()` method properly from the argument in most cases. You can improve this behavior with the following steps:
1. Use the third type parameter `"strict"`. This prevents inferring to `dispatchEvent<string>()`.
2. Make the `type` property of event definitions stricter.
```ts
type FooEvents = {
hello: CustomEvent & { type: "hello" }
hey: Event & { type: "hey" }
}
class Foo extends EventTarget<FooEvents, {}, "strict"> {
// ...
}
// Dispatching events
foo.dispatchEvent(new CustomEvent("hello", { detail: "detail" }))
// Error because `detail` property is lacking.
foo.dispatchEvent({ type: "hello" })
```

@@ -207,0 +233,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc