Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extending EventTarget in TypeScript (Angular 2+)?

Tags:

Is there a way to actually create a class, which will extend the EventTarget DOM API class?

Consider, I'm having this class:

class MyClass extends EventTarget {        

  constructor() {
    super();
  }

  private triggerEvent() {
    this.dispatchEvent(new Event('someEvent'));
  }

}

When I'm trying to instantiate it, I'm getting this error:

  • ERROR TypeError: Failed to construct 'EventTarget': Please use the 'new' operator, this DOM object constructor cannot be called as a function.

Looks like this is due to the fact, that this API requires proper ES2015 classes in order to work, but I'm transpiling my code down to ES5 level.

If I use a constructor like this:

constructor() {
  Reflect.construct(EventTarget, [], MyClass);
}

I'm getting the following error, when trying to invoke addEventListener() on the instance:

  • ERROR TypeError: Illegal invocation.

As a side effect, I'm also getting this TypeScript compilation error:

  • error TS2377: Constructors for derived classes must contain a 'super' call..
like image 506
Slava Fomin II Avatar asked Jul 14 '18 20:07

Slava Fomin II


1 Answers

The most simple solution would be to actually implement the EventTarget interface, but to delegate the actual implementation to some existing class, like DocumentFragment.

Also, we could extract this functionality to the reusable class:

export class DelegatedEventTarget implements EventTarget {

  private delegate = document.createDocumentFragment();


  addEventListener(...args: any): void {
    this.delegate.addEventListener.apply(this.delegate, args);
  }

  dispatchEvent(...args: any): boolean {
    return this.delegate.dispatchEvent.apply(this.delegate, args);
  }

  removeEventListener(...args: any): void {
    return this.delegate.removeEventListener.apply(this.delegate, args);
  }

}

Then, we can use it as a parent for our initial class:

class MyClass extends DelegatedEventTarget {

  private triggerEvent() {
    this.dispatchEvent(new Event('someEvent'));
  }

}

This will preserve the typings and will survive the compilation down to ES5.

like image 179
Slava Fomin II Avatar answered Sep 28 '22 19:09

Slava Fomin II