3

When we were still using Typescript 1.8.x in combination with the (Definitely Typed) type description files of React of that time, we used the 'Event' type to declare a 'generic' event in React component properties. We then could attach the value of that property (being and event handler function) to for example the 'onChange' property of an HtmlInputElement.

interface IIcoonProps {
    onClick?: Event;
}

interface IIcoonDetails {
    cssClass: string;
    standaardTooltip: string;
}

class Icoon extends React.Component<IIcoonProps, {}> {



public render(): JSX.Element {

    return (<span   className={klassenamen}
                    title={nieuweTooltip}
                    onClick={this.props.onClick} />);
    }
}

We recently updated to TypeScript 2.2.2 and also updated the type definitions that we're using. Now we can't use the generic 'Event' type anymore, because it will result in an exception like "Type 'Event' is not assignable to type 'EventHandler>'".

Of course when I change the type of the property in the properties interface of the custom component into 'React.MouseEvent', the problem is solved. But..... I don't want to have the parent component of this component to be aware of the underlying type (in this example HtmlInputElement), because it is an event that is mentioned in the properties of my own component. I only need to pass the event to the parent component, because I would like the parent component to be able to use the methods like 'PreventDefault' of the event. I am using different properties and methods within my IComponentProps interface to publish for example changed values of a text input.

The code below is working, but not desirable.

interface IIcoonProps {
    onClick?: React.EventHandler<React.MouseEvent<HTMLSpanElement>>;
}

interface IIcoonDetails {
    cssClass: string;
    standaardTooltip: string;
}

class Icoon extends React.Component<IIcoonProps, {}> {

public render(): JSX.Element {

    return (<span   className={klassenamen}
                    title={nieuweTooltip}
                    onClick={this.props.onClick} />);
    }
}

Does anybody know how, when using TypeScript and React one can use an generic type for an event like we did before when using the 'Event' type, without using generics (like MouseEvent).

Update: added code example

2
  • Can you please add a code example that shows the problem? Commented Apr 3, 2017 at 15:42
  • @NitzanTomer I added a code example. I don't want parent components to be aware that the underlying Html of the 'Icoon' component is an 'HtmlSpanElement'. When I need to change this in the future, I might need to change all components that are using the 'Icoon' component. Commented Apr 3, 2017 at 15:54

1 Answer 1

1

Your code seems fine to me, but if you don't want to be specific about the type of the target element then you can use HTMLElement:

interface IIcoonProps {
    onClick?: React.EventHandler<React.MouseEvent<HTMLElement>>;
}

That will work with future possible changes (let's say from HTMLSpanElement to HTMLDivElement).

Also, you can use this signature instead:

interface IIcoonProps {
    onClick?: (event: React.MouseEvent<HTMLElement>) => void;
}

Edit

If you want a non-generic interface to work with then you can create your own and then use that:

type MouseEvent = React.MouseEvent<HTMLElement>;

interface IIcoonProps {
    onClick?: (event: MouseEvent) => void;
}
Sign up to request clarification or add additional context in comments.

5 Comments

Not the answer I was hoping for, but it is what I expected. Thanks for the suggestion of using HtmlElement instead of the specialized tag.This will improve maintainability of the code.
What were you hoping for?
I was hoping for an interface that is not using generics and that exposes methods like preventDefault. I could add this interface as an optional parameter to a callback function.
Check my revised answer
That doesn't really change the solution but it looks simpler. MouseEvent is merely acting as an alias. I'm fine with your initial answer!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.