Skip to content

Commit 8b33ee2

Browse files
authored
fix(rxjs): no longer requires dom lib (#3566)
Adds interfaces to cover what is used from DOM in `fromEvent` so that types are carried through, but `dom` lib isn not required by default even if you are not using `fromEvent` fixes: #3558
1 parent f6318d6 commit 8b33ee2

File tree

2 files changed

+39
-35
lines changed

2 files changed

+39
-35
lines changed

compat/observable/FromEventObservable.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,16 @@ import { EventTargetLike } from 'rxjs/internal-compatibility';
33

44
export class FromEventObservable<T> extends Observable<T> {
55
/* tslint:disable:max-line-length */
6-
static create<T>(target: EventTargetLike, eventName: string): Observable<T>;
7-
static create<T>(target: EventTargetLike, eventName: string, selector: ((...args: any[]) => T)): Observable<T>;
8-
static create<T>(target: EventTargetLike, eventName: string, options: EventListenerOptions): Observable<T>;
9-
static create<T>(target: EventTargetLike, eventName: string, options: EventListenerOptions, selector: ((...args: any[]) => T)): Observable<T>;
6+
static create<T>(target: EventTargetLike<T>, eventName: string): Observable<T>;
7+
static create<T>(target: EventTargetLike<T>, eventName: string, selector: ((...args: any[]) => T)): Observable<T>;
8+
static create<T>(target: EventTargetLike<T>, eventName: string, options: EventListenerOptions): Observable<T>;
9+
static create<T>(target: EventTargetLike<T>, eventName: string, options: EventListenerOptions, selector: ((...args: any[]) => T)): Observable<T>;
1010
/* tslint:enable:max-line-length */
1111

12-
static create<T>(target: EventTargetLike,
12+
static create<T>(target: EventTargetLike<T>,
1313
eventName: string,
1414
options?: EventListenerOptions | ((...args: any[]) => T),
1515
selector?: ((...args: any[]) => T)): Observable<T> {
1616
return fromEvent(target, eventName, options as EventListenerOptions, selector);
1717
}
18-
}
18+
}

src/internal/observable/fromEvent.ts

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,38 @@ export interface NodeStyleEventEmitter {
1313

1414
export type NodeEventHandler = (...args: any[]) => void;
1515

16-
export type JQueryStyleEventEmitter = {
16+
export interface JQueryStyleEventEmitter {
1717
on: (eventName: string, handler: Function) => void;
1818
off: (eventName: string, handler: Function) => void;
19-
};
19+
}
20+
21+
export interface HasEventTargetAddRemove<E> {
22+
addEventListener(type: string, listener: ((evt: E) => void) | null, options?: boolean | AddEventListenerOptions): void;
23+
removeEventListener(type: string, listener?: ((evt: E) => void) | null, options?: EventListenerOptions | boolean): void;
24+
}
25+
26+
export type EventTargetLike<T> = HasEventTargetAddRemove<T> | NodeStyleEventEmitter | JQueryStyleEventEmitter;
2027

21-
export type EventTargetLike = EventTarget | NodeStyleEventEmitter | JQueryStyleEventEmitter | NodeList | HTMLCollection;
28+
export type FromEventTarget<T> = EventTargetLike<T> | ArrayLike<EventTargetLike<T>>;
2229

23-
export type EventListenerOptions = {
30+
export interface EventListenerOptions {
2431
capture?: boolean;
2532
passive?: boolean;
2633
once?: boolean;
27-
} | boolean;
34+
}
35+
36+
export interface AddEventListenerOptions extends EventListenerOptions {
37+
once?: boolean;
38+
passive?: boolean;
39+
}
2840

2941
/* tslint:disable:max-line-length */
30-
export function fromEvent<T>(target: EventTargetLike, eventName: string): Observable<T>;
42+
export function fromEvent<T>(target: FromEventTarget<T>, eventName: string): Observable<T>;
3143
/** @deprecated resultSelector no longer supported, pipe to map instead */
32-
export function fromEvent<T>(target: EventTargetLike, eventName: string, resultSelector: (...args: any[]) => T): Observable<T>;
33-
export function fromEvent<T>(target: EventTargetLike, eventName: string, options: EventListenerOptions): Observable<T>;
44+
export function fromEvent<T>(target: FromEventTarget<T>, eventName: string, resultSelector: (...args: any[]) => T): Observable<T>;
45+
export function fromEvent<T>(target: FromEventTarget<T>, eventName: string, options: EventListenerOptions): Observable<T>;
3446
/** @deprecated resultSelector no longer supported, pipe to map instead */
35-
export function fromEvent<T>(target: EventTargetLike, eventName: string, options: EventListenerOptions, resultSelector: (...args: any[]) => T): Observable<T>;
47+
export function fromEvent<T>(target: FromEventTarget<T>, eventName: string, options: EventListenerOptions, resultSelector: (...args: any[]) => T): Observable<T>;
3648
/* tslint:enable:max-line-length */
3749

3850
/**
@@ -138,7 +150,7 @@ export function fromEvent<T>(target: EventTargetLike, eventName: string, options
138150
* @see {@link bindNodeCallback}
139151
* @see {@link fromEventPattern}
140152
*
141-
* @param {EventTargetLike} target The DOM EventTarget, Node.js
153+
* @param {FromEventTarget<T>} target The DOM EventTarget, Node.js
142154
* EventEmitter, JQuery-like event target, NodeList or HTMLCollection to attach the event handler to.
143155
* @param {string} eventName The event name of interest, being emitted by the
144156
* `target`.
@@ -147,7 +159,7 @@ export function fromEvent<T>(target: EventTargetLike, eventName: string, options
147159
* @name fromEvent
148160
*/
149161
export function fromEvent<T>(
150-
target: EventTargetLike,
162+
target: FromEventTarget<T>,
151163
eventName: string,
152164
options?: EventListenerOptions | ((...args: any[]) => T),
153165
resultSelector?: ((...args: any[]) => T)
@@ -177,18 +189,18 @@ export function fromEvent<T>(
177189
});
178190
}
179191

180-
function setupSubscription<T>(sourceObj: EventTargetLike, eventName: string,
181-
handler: Function, subscriber: Subscriber<T>,
192+
function setupSubscription<T>(sourceObj: FromEventTarget<T>, eventName: string,
193+
handler: (...args: any[]) => void, subscriber: Subscriber<T>,
182194
options?: EventListenerOptions) {
183195
let unsubscribe: () => void;
184-
if (isNodeList(sourceObj) || isHTMLCollection(sourceObj)) {
185-
for (let i = 0, len = sourceObj.length; i < len; i++) {
196+
if (sourceObj && (sourceObj as any).length) {
197+
for (let i = 0, len = (sourceObj as any).length; i < len; i++) {
186198
setupSubscription(sourceObj[i], eventName, handler, subscriber, options);
187199
}
188200
} else if (isEventTarget(sourceObj)) {
189201
const source = sourceObj;
190-
sourceObj.addEventListener(eventName, handler as EventListener, options);
191-
unsubscribe = () => source.removeEventListener(eventName, handler as EventListener, options);
202+
sourceObj.addEventListener(eventName, handler, options);
203+
unsubscribe = () => source.removeEventListener(eventName, handler, options);
192204
} else if (isJQueryStyleEventEmitter(sourceObj)) {
193205
const source = sourceObj;
194206
sourceObj.on(eventName, handler);
@@ -205,21 +217,13 @@ function setupSubscription<T>(sourceObj: EventTargetLike, eventName: string,
205217
}
206218

207219
function isNodeStyleEventEmitter(sourceObj: any): sourceObj is NodeStyleEventEmitter {
208-
return !!sourceObj && typeof sourceObj.addListener === 'function' && typeof sourceObj.removeListener === 'function';
220+
return sourceObj && typeof sourceObj.addListener === 'function' && typeof sourceObj.removeListener === 'function';
209221
}
210222

211223
function isJQueryStyleEventEmitter(sourceObj: any): sourceObj is JQueryStyleEventEmitter {
212-
return !!sourceObj && typeof sourceObj.on === 'function' && typeof sourceObj.off === 'function';
213-
}
214-
215-
function isNodeList(sourceObj: any): sourceObj is NodeList {
216-
return !!sourceObj && toString.call(sourceObj) === '[object NodeList]';
217-
}
218-
219-
function isHTMLCollection(sourceObj: any): sourceObj is HTMLCollection {
220-
return !!sourceObj && toString.call(sourceObj) === '[object HTMLCollection]';
224+
return sourceObj && typeof sourceObj.on === 'function' && typeof sourceObj.off === 'function';
221225
}
222226

223-
function isEventTarget(sourceObj: any): sourceObj is EventTarget {
224-
return !!sourceObj && typeof sourceObj.addEventListener === 'function' && typeof sourceObj.removeEventListener === 'function';
227+
function isEventTarget(sourceObj: any): sourceObj is HasEventTargetAddRemove<any> {
228+
return sourceObj && typeof sourceObj.addEventListener === 'function' && typeof sourceObj.removeEventListener === 'function';
225229
}

0 commit comments

Comments
 (0)