From ea57c6a50b91bec9d872cd3d21a99e03b1bdb885 Mon Sep 17 00:00:00 2001 From: Nicholas Jamieson Date: Sun, 4 Apr 2021 22:24:12 +1000 Subject: [PATCH 1/5] test(fromEvent): make dtslint tests fail --- spec-dtslint/observables/fromEvent-spec.ts | 35 ++++++++++++++-------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/spec-dtslint/observables/fromEvent-spec.ts b/spec-dtslint/observables/fromEvent-spec.ts index 54b7af3555..797c459f9f 100644 --- a/spec-dtslint/observables/fromEvent-spec.ts +++ b/spec-dtslint/observables/fromEvent-spec.ts @@ -1,44 +1,55 @@ import { fromEvent } from 'rxjs'; -import { JQueryStyleEventEmitter } from '../../src/internal/observable/fromEvent'; -import { A, B } from '../helpers'; +import { + HasEventTargetAddRemove, + NodeStyleEventEmitter, + NodeCompatibleEventEmitter, + JQueryStyleEventEmitter +} from '../../src/internal/observable/fromEvent'; +import { B } from '../helpers'; declare const eventTargetSource: EventTarget; it('should support an event target source', () => { + const source: HasEventTargetAddRemove = eventTargetSource; const a = fromEvent(eventTargetSource, "click"); // $ExpectType Observable }); declare const documentSource: HTMLDocument; it('should support a document source', () => { + const source: HasEventTargetAddRemove = documentSource; const a = fromEvent(documentSource, "click"); // $ExpectType Observable }); -interface NodeStyleSource { - addListener: (eventName: string | symbol, handler: (...args: any[]) => void) => this; - removeListener: (eventName: string | symbol, handler: (...args: any[]) => void) => this; -}; - -declare const nodeStyleSource : NodeStyleSource; +// Pick the parts that will match NodeStyleEventEmitter. If this isn't done, it +// will match JQueryStyleEventEmitter - because of the `on` and `off` methods - +// despite the latter being declared last in the EventTargetLike union. +declare const nodeStyleSource: Pick; it('should support a node-style source', () => { + const source: NodeStyleEventEmitter = nodeStyleSource; const a = fromEvent(nodeStyleSource, "something"); // $ExpectType Observable const b = fromEvent(nodeStyleSource, "something"); // $ExpectType Observable }); -declare const nodeCompatibleSource: { - addListener: (eventName: string, handler: (...args: any[]) => void) => void; - removeListener: (eventName: string, handler: (...args: any[]) => void) => void; +const nodeCompatibleSource = { + addListener(eventName: "something", handler: () => void) {}, + removeListener(eventName: "something", handler: () => void) {} }; it('should support a node-compatible source', () => { + const source: NodeCompatibleEventEmitter = nodeCompatibleSource; const a = fromEvent(nodeCompatibleSource, "something"); // $ExpectType Observable const b = fromEvent(nodeCompatibleSource, "something"); // $ExpectType Observable }); -declare const jQueryStyleSource: JQueryStyleEventEmitter; +const jQueryStyleSource = { + on(eventName: "something", handler: (this: any, b: B) => any) {}, + off(eventName: "something", handler: (this: any, b: B) => any) {} +}; it('should support a jQuery-style source', () => { + const source: JQueryStyleEventEmitter = jQueryStyleSource; const a = fromEvent(jQueryStyleSource, "something"); // $ExpectType Observable const b = fromEvent(jQueryStyleSource, "something"); // $ExpectType Observable }); From fcf7d34aeb9c78dac271ed2e297255b6fcd2e85c Mon Sep 17 00:00:00 2001 From: Nicholas Jamieson Date: Sun, 4 Apr 2021 22:25:12 +1000 Subject: [PATCH 2/5] fix(fromEvent): use methods not props --- src/internal/observable/fromEvent.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/internal/observable/fromEvent.ts b/src/internal/observable/fromEvent.ts index d17c775d1d..2ab4be6a54 100644 --- a/src/internal/observable/fromEvent.ts +++ b/src/internal/observable/fromEvent.ts @@ -11,8 +11,8 @@ const eventTargetMethods = ['addEventListener', 'removeEventListener'] as const; const jqueryMethods = ['on', 'off'] as const; export interface NodeStyleEventEmitter { - addListener: (eventName: string | symbol, handler: NodeEventHandler) => this; - removeListener: (eventName: string | symbol, handler: NodeEventHandler) => this; + addListener(eventName: string | symbol, handler: NodeEventHandler): this; + removeListener(eventName: string | symbol, handler: NodeEventHandler): this; } export type NodeEventHandler = (...args: any[]) => void; @@ -21,15 +21,15 @@ export type NodeEventHandler = (...args: any[]) => void; // not use the same arguments or return EventEmitter values // such as React Native export interface NodeCompatibleEventEmitter { - addListener: (eventName: string, handler: NodeEventHandler) => void | {}; - removeListener: (eventName: string, handler: NodeEventHandler) => void | {}; + addListener(eventName: string, handler: NodeEventHandler): void | {}; + removeListener(eventName: string, handler: NodeEventHandler): void | {}; } // Use handler types like those in @types/jquery. See: // https://github.com/DefinitelyTyped/DefinitelyTyped/blob/847731ba1d7fa6db6b911c0e43aa0afe596e7723/types/jquery/misc.d.ts#L6395 export interface JQueryStyleEventEmitter { - on: (eventName: string, handler: (this: TContext, t: T, ...args: any[]) => any) => void; - off: (eventName: string, handler: (this: TContext, t: T, ...args: any[]) => any) => void; + on(eventName: string, handler: (this: TContext, t: T, ...args: any[]) => any): void; + off(eventName: string, handler: (this: TContext, t: T, ...args: any[]) => any): void; } export interface EventListenerObject { From ad8a36d0435c1da4c79ee3b05b7acbc0be4fb27e Mon Sep 17 00:00:00 2001 From: Nicholas Jamieson Date: Sun, 4 Apr 2021 22:53:27 +1000 Subject: [PATCH 3/5] refactor: remove redundant optional qualifiers --- src/internal/observable/fromEvent.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/internal/observable/fromEvent.ts b/src/internal/observable/fromEvent.ts index 2ab4be6a54..fb59bafb20 100644 --- a/src/internal/observable/fromEvent.ts +++ b/src/internal/observable/fromEvent.ts @@ -70,8 +70,8 @@ export interface AddEventListenerOptions extends EventListenerOptions { export function fromEvent(target: FromEventTarget, eventName: string): Observable; /** @deprecated resultSelector no longer supported, pipe to map instead */ -export function fromEvent(target: FromEventTarget, eventName: string, resultSelector?: (...args: any[]) => T): Observable; -export function fromEvent(target: FromEventTarget, eventName: string, options?: EventListenerOptions): Observable; +export function fromEvent(target: FromEventTarget, eventName: string, resultSelector: (...args: any[]) => T): Observable; +export function fromEvent(target: FromEventTarget, eventName: string, options: EventListenerOptions): Observable; /** @deprecated resultSelector no longer supported, pipe to map instead */ export function fromEvent( target: FromEventTarget, @@ -211,7 +211,7 @@ export function fromEvent( } if (resultSelector) { // DEPRECATED PATH - return fromEvent(target, eventName, options as EventListenerOptions | undefined).pipe(mapOneOrManyArgs(resultSelector)); + return fromEvent(target, eventName, options as EventListenerOptions).pipe(mapOneOrManyArgs(resultSelector)); } // Figure out our add and remove methods. In order to do this, From c8f7075732df9ac7865c2ae6125c0cc4a758468b Mon Sep 17 00:00:00 2001 From: Nicholas Jamieson Date: Sun, 4 Apr 2021 23:00:52 +1000 Subject: [PATCH 4/5] fix: result selector and target cannot both use T --- spec-dtslint/observables/fromEvent-spec.ts | 24 ++++++++++++++++++++-- src/internal/observable/fromEvent.ts | 4 ++-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/spec-dtslint/observables/fromEvent-spec.ts b/spec-dtslint/observables/fromEvent-spec.ts index 797c459f9f..738559fda9 100644 --- a/spec-dtslint/observables/fromEvent-spec.ts +++ b/spec-dtslint/observables/fromEvent-spec.ts @@ -14,6 +14,10 @@ it('should support an event target source', () => { const a = fromEvent(eventTargetSource, "click"); // $ExpectType Observable }); +it('should support an event target source result selector', () => { + const a = fromEvent(eventTargetSource, "click", () => "clunk"); // $ExpectType Observable +}); + declare const documentSource: HTMLDocument; it('should support a document source', () => { @@ -21,6 +25,10 @@ it('should support a document source', () => { const a = fromEvent(documentSource, "click"); // $ExpectType Observable }); +it('should support a document source result selector', () => { + const a = fromEvent(documentSource, "click", () => "clunk"); // $ExpectType Observable +}); + // Pick the parts that will match NodeStyleEventEmitter. If this isn't done, it // will match JQueryStyleEventEmitter - because of the `on` and `off` methods - // despite the latter being declared last in the EventTargetLike union. @@ -28,8 +36,12 @@ declare const nodeStyleSource: Pick { const source: NodeStyleEventEmitter = nodeStyleSource; - const a = fromEvent(nodeStyleSource, "something"); // $ExpectType Observable - const b = fromEvent(nodeStyleSource, "something"); // $ExpectType Observable + const a = fromEvent(nodeStyleSource, "exit"); // $ExpectType Observable + const b = fromEvent(nodeStyleSource, "exit"); // $ExpectType Observable +}); + +it('should support a node-style source result selector', () => { + const a = fromEvent(nodeStyleSource, "exit", () => "bye"); // $ExpectType Observable }); const nodeCompatibleSource = { @@ -43,6 +55,10 @@ it('should support a node-compatible source', () => { const b = fromEvent(nodeCompatibleSource, "something"); // $ExpectType Observable }); +it('should support a node-compatible source result selector', () => { + const a = fromEvent(nodeCompatibleSource, "something", () => "something else"); // $ExpectType Observable +}); + const jQueryStyleSource = { on(eventName: "something", handler: (this: any, b: B) => any) {}, off(eventName: "something", handler: (this: any, b: B) => any) {} @@ -53,3 +69,7 @@ it('should support a jQuery-style source', () => { const a = fromEvent(jQueryStyleSource, "something"); // $ExpectType Observable const b = fromEvent(jQueryStyleSource, "something"); // $ExpectType Observable }); + +it('should support a jQuery-style source result selector', () => { + const a = fromEvent(jQueryStyleSource, "something", () => "something else"); // $ExpectType Observable +}); diff --git a/src/internal/observable/fromEvent.ts b/src/internal/observable/fromEvent.ts index fb59bafb20..899337c6ea 100644 --- a/src/internal/observable/fromEvent.ts +++ b/src/internal/observable/fromEvent.ts @@ -70,11 +70,11 @@ export interface AddEventListenerOptions extends EventListenerOptions { export function fromEvent(target: FromEventTarget, eventName: string): Observable; /** @deprecated resultSelector no longer supported, pipe to map instead */ -export function fromEvent(target: FromEventTarget, eventName: string, resultSelector: (...args: any[]) => T): Observable; +export function fromEvent(target: FromEventTarget, eventName: string, resultSelector: (...args: any[]) => T): Observable; export function fromEvent(target: FromEventTarget, eventName: string, options: EventListenerOptions): Observable; /** @deprecated resultSelector no longer supported, pipe to map instead */ export function fromEvent( - target: FromEventTarget, + target: FromEventTarget, eventName: string, options: EventListenerOptions, resultSelector: (...args: any[]) => T From 36a823033357dc65b17e25f71d88f942c1fd67fb Mon Sep 17 00:00:00 2001 From: Nicholas Jamieson Date: Sun, 4 Apr 2021 23:08:44 +1000 Subject: [PATCH 5/5] chore: update api_guardian --- api_guard/dist/types/index.d.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api_guard/dist/types/index.d.ts b/api_guard/dist/types/index.d.ts index be1da4a92b..85a9b012ce 100644 --- a/api_guard/dist/types/index.d.ts +++ b/api_guard/dist/types/index.d.ts @@ -142,9 +142,9 @@ export declare function from>(input: O): Observab export declare function from>(input: O, scheduler: SchedulerLike): Observable>; export declare function fromEvent(target: FromEventTarget, eventName: string): Observable; -export declare function fromEvent(target: FromEventTarget, eventName: string, resultSelector?: (...args: any[]) => T): Observable; -export declare function fromEvent(target: FromEventTarget, eventName: string, options?: EventListenerOptions): Observable; -export declare function fromEvent(target: FromEventTarget, eventName: string, options: EventListenerOptions, resultSelector: (...args: any[]) => T): Observable; +export declare function fromEvent(target: FromEventTarget, eventName: string, resultSelector: (...args: any[]) => T): Observable; +export declare function fromEvent(target: FromEventTarget, eventName: string, options: EventListenerOptions): Observable; +export declare function fromEvent(target: FromEventTarget, eventName: string, options: EventListenerOptions, resultSelector: (...args: any[]) => T): Observable; export declare function fromEventPattern(addHandler: (handler: NodeEventHandler) => any, removeHandler?: (handler: NodeEventHandler, signal?: any) => void): Observable; export declare function fromEventPattern(addHandler: (handler: NodeEventHandler) => any, removeHandler?: (handler: NodeEventHandler, signal?: any) => void, resultSelector?: (...args: any[]) => T): Observable;