Flow: Get errors when using scroll event, i.e. addEventListener('scroll', ...)

Created on 16 Aug 2017  路  4Comments  路  Source: facebook/flow

Hi,

I use React and the following code:

scrollArea: HTMLElement;
tableBodyScrollHandler: EventListener;

this.scrollArea.addEventListener('scroll', this.tableBodyScrollHandler);

and I get errors:

 30:     this.scrollArea.addEventListener('scroll', this.tableBodyScrollHandler);
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call of method `addEventListener`. Function cannot be called on any member of intersection type
 30:     this.scrollArea.addEventListener('scroll', this.tableBodyScrollHandler);
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ intersection
  Member 1:
  158:   addEventListener(type: MouseEventTypes, listener: MouseEventListener, optionsOrUseCapture?: EventListenerOptionsOrUseCapture): void;
....

As I see there is no 'scroll' event in the https://github.com/facebook/flow/blob/v0.52.0/lib/dom.js#L142

Help please how to avoid this?

Accepting PRs Library definitions documentation

Most helpful comment

Ah, ok, that explains it. By adding the extra type information about target: HTMLElement, you're making the function's type different than what Flow expects, and so it isn't matching any of the addEventListener cases.

To avoid this problem, you can just test inside your callback whether the target is an element or not:

let x: HTMLElement | null = document.getElementById("Doc");
let handler: EventListener = (e: Event) => {
    if(e.target instanceof HTMLElement) {
    const width = e.target.offsetWidth;
    }
};

if(x) {
    x.addEventListener("scroll", handler)
}

Since this isn't a bug about flow itself, but just a usage question, I think we can take a note to add this e.target issue to the docs and then close this issue.

All 4 comments

I'm pretty sure the lack of "scroll" event isn't a problem, since there is another clause that allows any event name that's a string.

So for example, the most basic example of adding a scroll handler to an element works fine.

I notice that I get an error message a lot like the one you get if the type of the handler is wrong. Is the EventListener type in your code example the one built in to Flow, or one you defined yourself? Is it possible this.tableBodyScrollHandler isn't a valid EventListener by Flow's definition?

It would help to know something about the handler because it seems like that's where the types are failing to match. A small code example that fails would be really helpful.

@asolove Try, please, this:

let x: HTMLElement | null = document.getElementById("Doc");
let handler: EventListener = (e: Event & {target: HTMLElement}) => {
  const width = e.target.offsetWidth;
};

if(x) {
    x.addEventListener("scroll", handler)
}

What is the proper way to describe the 'handler'?
The only thing I found to fix it is to use 'any' type, but I don't think it's a good practice to use Flow.js

Ah, ok, that explains it. By adding the extra type information about target: HTMLElement, you're making the function's type different than what Flow expects, and so it isn't matching any of the addEventListener cases.

To avoid this problem, you can just test inside your callback whether the target is an element or not:

let x: HTMLElement | null = document.getElementById("Doc");
let handler: EventListener = (e: Event) => {
    if(e.target instanceof HTMLElement) {
    const width = e.target.offsetWidth;
    }
};

if(x) {
    x.addEventListener("scroll", handler)
}

Since this isn't a bug about flow itself, but just a usage question, I think we can take a note to add this e.target issue to the docs and then close this issue.

With eslint you may use window.HTMLElement instead of HTMLElement to avoid 'HTMLElement ' is not defined. warning.

Was this page helpful?
0 / 5 - 0 ratings