I'm having some issues strong typing this._onResize
and onMouseDown
.
At line 28, onMouseDown(event, this);
throws the error ESLint: Unsafe call of an any typed value.(@typescript-eslint/no-unsafe-call)
At line 37-38, this._handle.removeEventListener('mousedown', this._onResize);
and this._handle.removeEventListener('touchstart', this._onResize);
throw the error S2769: No overload matches this call.
.
For more detail, it says:
TS2769: No overload matches this call. Overload 1 of 2, '(type: keyof ElementEventMap, listener: (this: Element, ev: Event) => any, options?: boolean | EventListenerOptions | undefined): void', gave the following error. Argument of type '"mousedown"' is not assignable to parameter of type 'keyof ElementEventMap'. Overload 2 of 2, '(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions | undefined): void', gave the following error. Argument of type '((event: MouseEvent | TouchEvent) => void) | null | undefined' is not assignable to parameter of type 'EventListenerOrEventListenerObject'. Type 'undefined' is not assignable to type 'EventListenerOrEventListenerObject'.
My code is as follows:
import { Renderer2 } from '@angular/core';
export class ResizeHandle {
protected _handle: Element | undefined | null;
private _onResize: ((event: MouseEvent | TouchEvent) => void) | undefined | null;
constructor(
protected parent: Element,
protected renderer: Renderer2,
public type: string,
public css: string,
private onm ouseDown
) {
// generate handle div
const handle = renderer.createElement('div') as HTMLDivElement;
renderer.addClass(handle, 'resizable-handle');
renderer.addClass(handle, css);
// add default diagonal for se handle
if (type === 'se') {
renderer.addClass(handle, 'resizable-diagonal');
}
// append div to parent
if (this.parent) {
parent.appendChild(handle);
}
// create and register event listener
this._onResize = (event: MouseEvent | TouchEvent) => {
onMouseDown(event, this);
};
handle.addEventListener('mousedown', this._onResize, { passive: false });
handle.addEventListener('touchstart', this._onResize, { passive: false });
this._handle = handle;
}
dispose(): void {
if (this._handle) {
this._handle.removeEventListener('mousedown', this._onResize);
this._handle.removeEventListener('touchstart', this._onResize);
if (this.parent) {
this.parent.removeChild(this._handle);
}
}
this._handle = null;
this._onResize = null;
}
get element(): Element | undefined | null {
return this._handle;
}
}
What types need to be assigned to these values?
CodePudding user response:
The first thing to say is your code works fine, these are just TypeScript typing problems.
Your first problem, the unsafe call linting error, is because you haven't provided a type for onm ouseDown in the constructor signature. ESLint sees onm ouseDown is typed as 'any' and gets upset when you try to call it, because of the no-unsafe-call rule.
To fix this change the constructor signature as below:
constructor(
protected parent: Element,
protected renderer: Renderer2,
public type: string,
public css: string,
private onm ouseDown: (event: MouseEvent | TouchEvent, rh: ResizeHandle) => void
) {
Your second problem is caused by having strictFunctionTypes set to true, and then trying to pass a strongly-typed event listener to removeEventListener which just wants an EventListener type. The workaround is simply to cast _onResize to EventListener in dispose() as below:
this._handle.removeEventListener('mousedown', this._onResize as EventListener);
this._handle.removeEventListener('touchstart', this._onResize as EventListener);