Home > Blockchain >  Strong typing eventListener calls
Strong typing eventListener calls

Time:10-21

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);
  • Related