Skip to content

Commit 17c4d41

Browse files
authored
🤖 Merge PR DefinitelyTyped#72883 node: add DOM CustomEvent to v20/v22 by @Renegade334
1 parent 96890be commit 17c4d41

File tree

10 files changed

+205
-331
lines changed

10 files changed

+205
-331
lines changed

types/aws-lambda/aws-lambda-tests.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -107,16 +107,16 @@ context.succeed(str, anyObj);
107107
context.fail(error);
108108
context.fail(str);
109109

110-
interface CustomEvent {
110+
interface CustomTEvent {
111111
eventString: string;
112112
eventBool: boolean;
113113
}
114-
interface CustomResult {
114+
interface CustomTResult {
115115
resultString: string;
116116
resultBool?: boolean | undefined;
117117
}
118-
type CustomHandler = AWSLambda.Handler<CustomEvent, CustomResult>;
119-
type CustomCallback = AWSLambda.Callback<CustomResult>;
118+
type CustomHandler = AWSLambda.Handler<CustomTEvent, CustomTResult>;
119+
type CustomCallback = AWSLambda.Callback<CustomTResult>;
120120

121121
// Untyped handlers should work
122122
const untypedAsyncHandler: AWSLambda.Handler = async (event, context, cb) => {
@@ -161,13 +161,13 @@ const unsafeAsyncHandler: CustomHandler = async (event, context, cb) => {
161161

162162
// Test safe old style still works
163163
const typedCallbackHandler: CustomHandler = (event, context, cb) => {
164-
// $ExpectType CustomEvent
164+
// $ExpectType CustomTEvent
165165
event;
166166
str = event.eventString;
167167
// $ExpectType Context
168168
context;
169169
str = context.functionName;
170-
// $ExpectType Callback<CustomResult>
170+
// $ExpectType Callback<CustomTResult>
171171
cb;
172172
cb();
173173
cb(null);
@@ -181,11 +181,11 @@ const typedCallbackHandler: CustomHandler = (event, context, cb) => {
181181

182182
// Test preferred new type
183183
const typedAsyncHandler: CustomHandler = async (event, context, cb) => {
184-
// $ExpectType CustomEvent
184+
// $ExpectType CustomTEvent
185185
event;
186186
// $ExpectType Context
187187
context;
188-
// $ExpectType Callback<CustomResult>
188+
// $ExpectType Callback<CustomTResult>
189189
cb;
190190
// Can still use callback
191191
cb(null, { resultString: str });
@@ -197,7 +197,7 @@ const badTypedAsyncHandler: CustomHandler = async (event, context, cb) => ({ res
197197

198198
// Test using untyped Callback type still works.
199199
const mixedUntypedCallbackTypedHandler: CustomHandler = (
200-
event: CustomEvent,
200+
event: CustomTEvent,
201201
context: AWSLambda.Context,
202202
cb: AWSLambda.Callback,
203203
) => {};

types/node/dom-events.d.ts

Lines changed: 60 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,95 +1,68 @@
1-
export {}; // Don't export anything!
1+
// Make this a module
2+
export {};
23

3-
//// DOM-like Events
4-
// NB: The Event / EventTarget / EventListener implementations below were copied
5-
// from lib.dom.d.ts, then edited to reflect Node's documentation at
6-
// https://nodejs.org/api/events.html#class-eventtarget.
7-
// Please read that link to understand important implementation differences.
4+
// Conditional type aliases, which are later merged into the global scope.
5+
// Will either be empty if the relevant web library is already present, or the @types/node definition otherwise.
86

9-
// This conditional type will be the existing global Event in a browser, or
10-
// the copy below in a Node environment.
11-
type __Event = typeof globalThis extends { onmessage: any; Event: any } ? {}
12-
: {
13-
/** This is not used in Node.js and is provided purely for completeness. */
14-
readonly bubbles: boolean;
15-
/** Alias for event.stopPropagation(). This is not used in Node.js and is provided purely for completeness. */
16-
cancelBubble: () => void;
17-
/** True if the event was created with the cancelable option */
18-
readonly cancelable: boolean;
19-
/** This is not used in Node.js and is provided purely for completeness. */
20-
readonly composed: boolean;
21-
/** Returns an array containing the current EventTarget as the only entry or empty if the event is not being dispatched. This is not used in Node.js and is provided purely for completeness. */
22-
composedPath(): [EventTarget?];
23-
/** Alias for event.target. */
24-
readonly currentTarget: EventTarget | null;
25-
/** Is true if cancelable is true and event.preventDefault() has been called. */
26-
readonly defaultPrevented: boolean;
27-
/** This is not used in Node.js and is provided purely for completeness. */
28-
readonly eventPhase: 0 | 2;
29-
/** The `AbortSignal` "abort" event is emitted with `isTrusted` set to `true`. The value is `false` in all other cases. */
30-
readonly isTrusted: boolean;
31-
/** Sets the `defaultPrevented` property to `true` if `cancelable` is `true`. */
32-
preventDefault(): void;
33-
/** This is not used in Node.js and is provided purely for completeness. */
34-
returnValue: boolean;
35-
/** Alias for event.target. */
36-
readonly srcElement: EventTarget | null;
37-
/** Stops the invocation of event listeners after the current one completes. */
38-
stopImmediatePropagation(): void;
39-
/** This is not used in Node.js and is provided purely for completeness. */
40-
stopPropagation(): void;
41-
/** The `EventTarget` dispatching the event */
42-
readonly target: EventTarget | null;
43-
/** The millisecond timestamp when the Event object was created. */
44-
readonly timeStamp: number;
45-
/** Returns the type of event, e.g. "click", "hashchange", or "submit". */
46-
readonly type: string;
47-
};
7+
type __Event = typeof globalThis extends { onmessage: any } ? {} : Event;
8+
interface Event {
9+
readonly bubbles: boolean;
10+
cancelBubble: boolean;
11+
readonly cancelable: boolean;
12+
readonly composed: boolean;
13+
composedPath(): [EventTarget?];
14+
readonly currentTarget: EventTarget | null;
15+
readonly defaultPrevented: boolean;
16+
readonly eventPhase: 0 | 2;
17+
initEvent(type: string, bubbles?: boolean, cancelable?: boolean): void;
18+
readonly isTrusted: boolean;
19+
preventDefault(): void;
20+
readonly returnValue: boolean;
21+
readonly srcElement: EventTarget | null;
22+
stopImmediatePropagation(): void;
23+
stopPropagation(): void;
24+
readonly target: EventTarget | null;
25+
readonly timeStamp: number;
26+
readonly type: string;
27+
}
4828

49-
// See comment above explaining conditional type
50-
type __EventTarget = typeof globalThis extends { onmessage: any; EventTarget: any } ? {}
51-
: {
52-
/**
53-
* Adds a new handler for the `type` event. Any given `listener` is added only once per `type` and per `capture` option value.
54-
*
55-
* If the `once` option is true, the `listener` is removed after the next time a `type` event is dispatched.
56-
*
57-
* The `capture` option is not used by Node.js in any functional way other than tracking registered event listeners per the `EventTarget` specification.
58-
* Specifically, the `capture` option is used as part of the key when registering a `listener`.
59-
* Any individual `listener` may be added once with `capture = false`, and once with `capture = true`.
60-
*/
61-
addEventListener(
62-
type: string,
63-
listener: EventListener | EventListenerObject,
64-
options?: AddEventListenerOptions | boolean,
65-
): void;
66-
/** 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. */
67-
dispatchEvent(event: Event): boolean;
68-
/** Removes the event listener in target's event listener list with the same type, callback, and options. */
69-
removeEventListener(
70-
type: string,
71-
listener: EventListener | EventListenerObject,
72-
options?: EventListenerOptions | boolean,
73-
): void;
74-
};
29+
type __CustomEvent<T = any> = typeof globalThis extends { onmessage: any } ? {} : CustomEvent<T>;
30+
interface CustomEvent<T = any> extends Event {
31+
readonly detail: T;
32+
}
33+
34+
type __EventTarget = typeof globalThis extends { onmessage: any } ? {} : EventTarget;
35+
interface EventTarget {
36+
addEventListener(
37+
type: string,
38+
listener: EventListener | EventListenerObject,
39+
options?: AddEventListenerOptions | boolean,
40+
): void;
41+
dispatchEvent(event: Event): boolean;
42+
removeEventListener(
43+
type: string,
44+
listener: EventListener | EventListenerObject,
45+
options?: EventListenerOptions | boolean,
46+
): void;
47+
}
7548

7649
interface EventInit {
7750
bubbles?: boolean;
7851
cancelable?: boolean;
7952
composed?: boolean;
8053
}
8154

55+
interface CustomEventInit<T = any> extends EventInit {
56+
detail?: T;
57+
}
58+
8259
interface EventListenerOptions {
83-
/** Not directly used by Node.js. Added for API completeness. Default: `false`. */
8460
capture?: boolean;
8561
}
8662

8763
interface AddEventListenerOptions extends EventListenerOptions {
88-
/** When `true`, the listener is automatically removed when it is first invoked. Default: `false`. */
8964
once?: boolean;
90-
/** When `true`, serves as a hint that the listener will not call the `Event` object's `preventDefault()` method. Default: false. */
9165
passive?: boolean;
92-
/** The listener will be removed when the given AbortSignal object's `abort()` method is called. */
9366
signal?: AbortSignal;
9467
}
9568

@@ -101,24 +74,26 @@ interface EventListenerObject {
10174
handleEvent(object: Event): void;
10275
}
10376

104-
import {} from "events"; // Make this an ambient declaration
77+
// Merge conditional interfaces into global scope, and conditionally declare global constructors.
10578
declare global {
106-
/** An event which takes place in the DOM. */
10779
interface Event extends __Event {}
10880
var Event: typeof globalThis extends { onmessage: any; Event: infer T } ? T
10981
: {
110-
prototype: __Event;
111-
new(type: string, eventInitDict?: EventInit): __Event;
82+
prototype: Event;
83+
new(type: string, eventInitDict?: EventInit): Event;
84+
};
85+
86+
interface CustomEvent<T = any> extends __CustomEvent<T> {}
87+
var CustomEvent: typeof globalThis extends { onmessage: any; CustomEvent: infer T } ? T
88+
: {
89+
prototype: CustomEvent;
90+
new<T>(type: string, eventInitDict?: CustomEventInit<T>): CustomEvent<T>;
11291
};
11392

114-
/**
115-
* EventTarget is a DOM interface implemented by objects that can
116-
* receive events and may have listeners for them.
117-
*/
11893
interface EventTarget extends __EventTarget {}
11994
var EventTarget: typeof globalThis extends { onmessage: any; EventTarget: infer T } ? T
12095
: {
121-
prototype: __EventTarget;
122-
new(): __EventTarget;
96+
prototype: EventTarget;
97+
new(): EventTarget;
12398
};
12499
}

types/node/test/events-dom.ts

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,15 @@
1-
//// Test global event interfaces
2-
31
{
4-
const e: Event = new Event("");
5-
e.preventDefault();
6-
// @ts-expect-error - ensure constructor does not return a constructor
7-
new e();
8-
92
// Node's "DOM-like" Event differs from the real DOM in a few key aspects
10-
// $ExpectType boolean
11-
e.cancelBubble;
12-
e.composedPath();
3+
const evt = new Event("");
4+
// $ExpectType EventTarget
5+
evt.composedPath()[1];
136
// $ExpectType number
14-
e.eventPhase;
7+
evt.eventPhase;
8+
9+
const ce = new CustomEvent("", { detail: "" });
10+
// $ExpectType string
11+
ce.detail;
1512

1613
const et: EventTarget = new EventTarget();
1714
et.addEventListener("", () => {}, { passive: true });
18-
// @ts-expect-error - ensure constructor does not return a constructor
19-
new et();
2015
}

types/node/test/events-non-dom.ts

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,15 @@
1-
//// Test global event interfaces
2-
31
{
42
// Some event properties differ from DOM types
5-
const evt = new Event("fake");
6-
evt.cancelBubble();
3+
const evt = new Event("");
74
// @ts-expect-error
8-
evt.composedPath[2];
5+
evt.composedPath[1];
96
// $ExpectType 0 | 2
107
evt.eventPhase;
118

12-
// @ts-expect-error - ensure constructor does not return a constructor
13-
new evt();
9+
const ce = new CustomEvent("", { detail: "" });
10+
// $ExpectType string
11+
ce.detail;
1412

1513
const et: EventTarget = new EventTarget();
1614
et.addEventListener("", () => {}, { passive: true });
17-
// @ts-expect-error - ensure constructor does not return a constructor
18-
new et();
1915
}

0 commit comments

Comments
 (0)