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?
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.
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 theaddEventListenercases.To avoid this problem, you can just test inside your callback whether the target is an element or not:
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.targetissue to the docs and then close this issue.