-
Notifications
You must be signed in to change notification settings - Fork 2
Description
You can create 2 versions of these, one with arbituary string keys (scroll below to bottom, just enforce a singly typed event) and the other requiring specific string keys (the current version you are using).
Also, for the one with specific string keys, is there a way to use regular dispatchEvent instead of deprecrating it in favour of dispatchedTypeEvent?? I guess that is not possible because the native JAvascript Event enforces arbituary string types internally hmmm...
Possible issue, regarding https://github.com/DerZade/typescript-event-target#dispatching-events, you can't enforce specific string keys for events that are being dispatched though...
const eventTarget = new TypedKeyEventTarget<{"time":MouseEvent}>();
eventTarget.dispatchTypedEvent(
'time',
new MouseEvent('doesnt match above if mispelled will not work')
);
Typically, most enforced string keys are found as static constants within the class itself as a lookup to avoid typos, but compiler wise it wil still accept rather than reject.
// Typed KeyEventTarget version
export type TypedEventListener<M, T extends keyof M> = (
evt: M[T]
) => void | Promise<void>;
export interface TypedEventListenerObject<M, T extends keyof M> {
handleEvent: (evt: M[T]) => void | Promise<void>;
}
export type TypedEventListenerOrEventListenerObject<M, T extends keyof M> =
| TypedEventListener<M, T>
| TypedEventListenerObject<M, T>;
type ValueIsEvent<T> = {
[key in keyof T]: Event;
};
export interface TypedKeyEventTarget<M extends ValueIsEvent<M>> {
/** Appends an event listener for events whose type attribute value is type.
* The callback argument sets the callback that will be invoked when the event
* is dispatched.
*
* The options argument sets listener-specific options. For compatibility this
* can be a boolean, in which case the method behaves exactly as if the value
* was specified as options's capture.
*
* When set to true, options's capture prevents callback from being invoked
* when the event's eventPhase attribute value is BUBBLING_PHASE. When false
* (or not present), callback will not be invoked when event's eventPhase
* attribute value is CAPTURING_PHASE. Either way, callback will be invoked if
* event's eventPhase attribute value is AT_TARGET.
*
* When set to true, options's passive indicates that the callback will not
* cancel the event by invoking preventDefault(). This is used to enable
* performance optimizations described in § 2.8 Observing event listeners.
*
* When set to true, options's once indicates that the callback will only be
* invoked once after which the event listener will be removed.
*
* The event listener is appended to target's event listener list and is not
* appended if it has the same type, callback, and capture. */
addEventListener: <T extends keyof M & string>(
type: string,
listener: TypedEventListenerOrEventListenerObject<M, T> | null,
options?: boolean | AddEventListenerOptions
) => void;
/** Removes the event listener in target's event listener list with the same
* type, callback, and options. */
removeEventListener: <T extends keyof M & string>(
type: T,
callback: TypedEventListenerOrEventListenerObject<M, T> | null,
options?: EventListenerOptions | boolean
) => void;
/**
* Dispatches a synthetic event event to target and returns true if either
* event's cancelable attribute value is false or its preventDefault() method
* was not invoked, and false otherwise.
* @deprecated To ensure type safety use `dispatchTypedEvent` instead.
*/
dispatchEvent: (event: Event) => boolean;
}
export class TypedKeyEventTarget<M extends ValueIsEvent<M>> extends EventTarget {
/**
* Dispatches a synthetic event event to target and returns true if either
* event's cancelable attribute value is false or its preventDefault() method
* was not invoked, and false otherwise.
*/
public dispatchTypedEvent<T extends keyof M>(
_type: T,
event: M[T]
): boolean {
return super.dispatchEvent(event);
}
}
// Typed event version (Partial M) (with arbituary string keys)
interface MEventListener<M extends Event> {
(evt: M): void;
}
interface MEventListenerObject<M extends Event> {
handleEvent(object: M): void;
}
export interface TypedEventTarget<_M extends Event> {
/** Appends an event listener for events whose type attribute value is type.
* The callback argument sets the callback that will be invoked when the event
* is dispatched.
*
* The options argument sets listener-specific options. For compatibility this
* can be a boolean, in which case the method behaves exactly as if the value
* was specified as options's capture.
*
* When set to true, options's capture prevents callback from being invoked
* when the event's eventPhase attribute value is BUBBLING_PHASE. When false
* (or not present), callback will not be invoked when event's eventPhase
* attribute value is CAPTURING_PHASE. Either way, callback will be invoked if
* event's eventPhase attribute value is AT_TARGET.
*
* When set to true, options's passive indicates that the callback will not
* cancel the event by invoking preventDefault(). This is used to enable
* performance optimizations described in § 2.8 Observing event listeners.
*
* When set to true, options's once indicates that the callback will only be
* invoked once after which the event listener will be removed.
*
* The event listener is appended to target's event listener list and is not
* appended if it has the same type, callback, and capture. */
addEventListener: (
type: string,
listener: MEventListener<_M> | MEventListenerObject<_M> | null,
options?: boolean | AddEventListenerOptions
) => void;
/** Removes the event listener in target's event listener list with the same
* type, callback, and options. */
removeEventListener: (
type: string,
callback: MEventListener<_M> | MEventListenerObject<_M> | null,
options?: EventListenerOptions | boolean
) => void;
/**
* Dispatches a synthetic event event to target and returns true if either
* event's cancelable attribute value is false or its preventDefault() method
* was not invoked, and false otherwise.
*/
dispatchEvent: (event: _M) => boolean
}
export class TypedEventTarget<_M> extends EventTarget {}