Event and React SyntheticEvent are currently defined as something like:
declare class Event {
target: EventTarget;
Which means that the exact type of target is not known
var Foo = React.createClass({
render() {
return (
<input type="checkbox" onChange={this._onChange} />
);
},
_onChange(evt: SyntheticEvent): void {
console.log(evt.target.checked); // Flow error (property 'checked' not found in EventTarget)
}
})
It seems like this could be solved if Event and SyntheticEvent were generic types, something like:
declare class SyntheticEvent<TElement : EventTarget> {
target: TElement;
_onChange(evt: SyntheticEvent<HTMLInputElement>): void {
console.log(evt.target.checked); // Should work since we know that evt.target is HTMLInputElement
}
Any plans here? Working with forms would be much more pleasant with a fix.
We've definitely considered this, but it trades soundness for convenience. Do you think it's worth making the model unsound?
For example,
declare var elem: HTMLElement;
elem.addEventListener("mouseover", (event: Event<HTMLInputElement>) => {
event.target.value; // event.target isn't necessarily HTMLInputElement here
});
To make this sound, we would need to constrain addEventListener to only accept callbacks that are compatible with the event type, which means enumerating every possible event type and defaulting to something strict.
Do you think it's worth making the model unsound?
Personally I think that it's worth adding, even if it makes the code unsound. I don't think it's any worse than what people would be doing today - Any event handler code today is most likely using a catchall type like Object or any for the event, or the developer is writing their own typedef. For example, in my code I do something like this:
_onChange(evt: {target: {checked: boolean}}): void {
console.log(evt.target.checked);
}
Also worth mentioning: We've also been chatting a bit about having type-parameter defaults (along the lines of type Event<Target=EventTarget> = ...).
This would let users write something like (event: Event<>) => ... if they want to be strict, or (event: Event<HTMLInputElement>) => ... if the structure of the app is such that the event is definitely always targeting an input element.
(cc @gabelevi @bhosmer )
FYI, Type param defaults went out in 0.24: https://github.com/facebook/flow/blob/master/Changelog.md#v0240
Closing as this will be addressed in an upcoming release for React. If someone wants to contribute this for DOM events feel free to send a PR 馃憤
Closing as this will be addressed in an upcoming release for React. If someone wants to contribute this for DOM events feel free to send a PR 馃憤
Was this ever addressed, and how?
@callumlocke See the docs here: https://flow.org/en/docs/react/events/
To type event handlers you may use the
SyntheticEvent<T>types
Most helpful comment
Also worth mentioning: We've also been chatting a bit about having type-parameter defaults (along the lines of
type Event<Target=EventTarget> = ...).This would let users write something like
(event: Event<>) => ...if they want to be strict, or(event: Event<HTMLInputElement>) => ...if the structure of the app is such that the event is definitely always targeting an input element.(cc @gabelevi @bhosmer )