未验证 提交 ea5d7068 编写于 作者: M Matt Bierner 提交者: GitHub

Fix dom on for TS's strict function mode (#37748)

**background**
TS 2.6 introduces a new strict function checking mode. This can catch many common mistakes such as patterns like this:

```js
function on(callback: (Base) => void) { ... }

on((e: Sub) =>  {...});
```

This does an implicit cast in the call to `on`. With strict function checking, this is now flagged as an error

**Change**
This change fixes dom.on so that it works with strict function checking. This done by making it generic so that the type of the event taken in the callback can be inferred from the callback itself.
上级 7bf5879c
......@@ -559,9 +559,9 @@ export class Builder implements IDisposable {
/**
* Registers listener on event types on the current element.
*/
public on(type: string, fn: (e: Event, builder: Builder, unbind: IDisposable) => void, listenerToUnbindContainer?: IDisposable[], useCapture?: boolean): Builder;
public on(typeArray: string[], fn: (e: Event, builder: Builder, unbind: IDisposable) => void, listenerToUnbindContainer?: IDisposable[], useCapture?: boolean): Builder;
public on(arg1: any, fn: (e: Event, builder: Builder, unbind: IDisposable) => void, listenerToUnbindContainer?: IDisposable[], useCapture?: boolean): Builder {
public on<E extends Event = Event>(type: string, fn: (e: E, builder: Builder, unbind: IDisposable) => void, listenerToUnbindContainer?: IDisposable[], useCapture?: boolean): Builder;
public on<E extends Event = Event>(typeArray: string[], fn: (e: E, builder: Builder, unbind: IDisposable) => void, listenerToUnbindContainer?: IDisposable[], useCapture?: boolean): Builder;
public on<E extends Event = Event>(arg1: any, fn: (e: E, builder: Builder, unbind: IDisposable) => void, listenerToUnbindContainer?: IDisposable[], useCapture?: boolean): Builder {
// Event Type Array
if (types.isArray(arg1)) {
......@@ -575,7 +575,7 @@ export class Builder implements IDisposable {
let type = arg1;
// Add Listener
let unbind: IDisposable = DOM.addDisposableListener(this.currentElement, type, (e: Event) => {
let unbind: IDisposable = DOM.addDisposableListener(this.currentElement, type, (e) => {
fn(e, this, unbind); // Pass in Builder as Second Argument
}, useCapture || false);
......@@ -641,9 +641,9 @@ export class Builder implements IDisposable {
* Registers listener on event types on the current element and removes
* them after first invocation.
*/
public once(type: string, fn: (e: Event, builder: Builder, unbind: IDisposable) => void, listenerToUnbindContainer?: IDisposable[], useCapture?: boolean): Builder;
public once(typesArray: string[], fn: (e: Event, builder: Builder, unbind: IDisposable) => void, listenerToUnbindContainer?: IDisposable[], useCapture?: boolean): Builder;
public once(arg1: any, fn: (e: Event, builder: Builder, unbind: IDisposable) => void, listenerToUnbindContainer?: IDisposable[], useCapture?: boolean): Builder {
public once<E extends Event = Event>(type: string, fn: (e: E, builder: Builder, unbind: IDisposable) => void, listenerToUnbindContainer?: IDisposable[], useCapture?: boolean): Builder;
public once<E extends Event = Event>(typesArray: string[], fn: (e: E, builder: Builder, unbind: IDisposable) => void, listenerToUnbindContainer?: IDisposable[], useCapture?: boolean): Builder;
public once<E extends Event = Event>(arg1: any, fn: (e: E, builder: Builder, unbind: IDisposable) => void, listenerToUnbindContainer?: IDisposable[], useCapture?: boolean): Builder {
// Event Type Array
if (types.isArray(arg1)) {
......@@ -657,7 +657,7 @@ export class Builder implements IDisposable {
let type = arg1;
// Add Listener
let unbind: IDisposable = DOM.addDisposableListener(this.currentElement, type, (e: Event) => {
let unbind: IDisposable = DOM.addDisposableListener(this.currentElement, type, (e) => {
fn(e, this, unbind); // Pass in Builder as Second Argument
unbind.dispose();
}, useCapture || false);
......
......@@ -413,18 +413,18 @@ class AnimationFrameQueueItem implements IDisposable {
/**
* Add a throttled listener. `handler` is fired at most every 16ms or with the next animation frame (if browser supports it).
*/
export interface IEventMerger<R> {
(lastEvent: R, currentEvent: Event): R;
export interface IEventMerger<R, E> {
(lastEvent: R, currentEvent: E): R;
}
const MINIMUM_TIME_MS = 16;
const DEFAULT_EVENT_MERGER: IEventMerger<Event> = function (lastEvent: Event, currentEvent: Event) {
const DEFAULT_EVENT_MERGER: IEventMerger<Event, Event> = function (lastEvent: Event, currentEvent: Event) {
return currentEvent;
};
class TimeoutThrottledDomListener<R> extends Disposable {
class TimeoutThrottledDomListener<R, E extends Event> extends Disposable {
constructor(node: any, type: string, handler: (event: R) => void, eventMerger: IEventMerger<R> = <any>DEFAULT_EVENT_MERGER, minimumTimeMs: number = MINIMUM_TIME_MS) {
constructor(node: any, type: string, handler: (event: R) => void, eventMerger: IEventMerger<R, E> = <any>DEFAULT_EVENT_MERGER, minimumTimeMs: number = MINIMUM_TIME_MS) {
super();
let lastEvent: R = null;
......@@ -452,8 +452,8 @@ class TimeoutThrottledDomListener<R> extends Disposable {
}
}
export function addDisposableThrottledListener<R>(node: any, type: string, handler: (event: R) => void, eventMerger?: IEventMerger<R>, minimumTimeMs?: number): IDisposable {
return new TimeoutThrottledDomListener<R>(node, type, handler, eventMerger, minimumTimeMs);
export function addDisposableThrottledListener<R, E extends Event = Event>(node: any, type: string, handler: (event: R) => void, eventMerger?: IEventMerger<R, E>, minimumTimeMs?: number): IDisposable {
return new TimeoutThrottledDomListener<R, E>(node, type, handler, eventMerger, minimumTimeMs);
}
export function getComputedStyle(el: HTMLElement): CSSStyleDeclaration {
......
......@@ -96,7 +96,7 @@ export class GlobalMouseMoveMonitor<R> extends Disposable {
for (let i = 0; i < windowChain.length; i++) {
this.hooks.push(dom.addDisposableThrottledListener(windowChain[i].window.document, 'mousemove',
(data: R) => this.mouseMoveCallback(data),
(lastEvent: R, currentEvent: MouseEvent) => this.mouseMoveEventMerger(lastEvent, currentEvent)
(lastEvent: R, currentEvent) => this.mouseMoveEventMerger(lastEvent, currentEvent as MouseEvent)
));
this.hooks.push(dom.addDisposableListener(windowChain[i].window.document, 'mouseup', (e: MouseEvent) => this.stopMonitoring(true)));
}
......
......@@ -135,10 +135,10 @@ export class EditorMouseEventFactory {
}
public onMouseMoveThrottled(target: HTMLElement, callback: (e: EditorMouseEvent) => void, merger: EditorMouseEventMerger, minimumTimeMs: number): IDisposable {
let myMerger: dom.IEventMerger<EditorMouseEvent> = (lastEvent: EditorMouseEvent, currentEvent: MouseEvent): EditorMouseEvent => {
let myMerger: dom.IEventMerger<EditorMouseEvent, MouseEvent> = (lastEvent: EditorMouseEvent, currentEvent: MouseEvent): EditorMouseEvent => {
return merger(lastEvent, this._create(currentEvent));
};
return dom.addDisposableThrottledListener<EditorMouseEvent>(target, 'mousemove', callback, myMerger, minimumTimeMs);
return dom.addDisposableThrottledListener<EditorMouseEvent, MouseEvent>(target, 'mousemove', callback, myMerger, minimumTimeMs);
}
}
......@@ -168,7 +168,7 @@ export class GlobalEditorMouseMoveMonitor extends Disposable {
this._globalMouseMoveMonitor.stopMonitoring(true);
}, true);
let myMerger: dom.IEventMerger<EditorMouseEvent> = (lastEvent: EditorMouseEvent, currentEvent: MouseEvent): EditorMouseEvent => {
let myMerger: dom.IEventMerger<EditorMouseEvent, MouseEvent> = (lastEvent: EditorMouseEvent, currentEvent: MouseEvent): EditorMouseEvent => {
return merger(lastEvent, new EditorMouseEvent(currentEvent, this._editorViewDomNode));
};
......
......@@ -190,8 +190,8 @@ export class TextFileEditor extends BaseTextEditor {
// Best we can do is to reveal the folder in the explorer
if (this.contextService.isInsideWorkspace(input.getResource())) {
this.viewletService.openViewlet(VIEWLET_ID, true).done((viewlet: ExplorerViewlet) => {
return viewlet.getExplorerView().select(input.getResource(), true);
this.viewletService.openViewlet(VIEWLET_ID, true).done(viewlet => {
return (viewlet as ExplorerViewlet).getExplorerView().select(input.getResource(), true);
}, errors.onUnexpectedError);
}
}, errors.onUnexpectedError);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册