Skip to content Skip to sidebar Skip to footer

Typesafe Select Onchange Event Using Reactjs And Typescript

I have figured out how to tie up an event handler on a SELECT element using an ugly cast of the event to any. Is it possible to retrieve the value in a type-safe manner without cas

Solution 1:

I tried using React.FormEvent<HTMLSelectElement> but it led to an error in the editor, even though there is no EventTarget visible in the code:

The property 'value' does not exist on value of type 'EventTarget'

Then I changed React.FormEvent to React.ChangeEvent and it helped:

privatechangeName(event: React.ChangeEvent<HTMLSelectElement>) {
    event.preventDefault();
    this.props.actions.changeName(event.target.value);
}

Solution 2:

Since upgrading my typings to react 0.14.43 (I'm not sure exactly when this was introduced), the React.FormEvent type is now generic and this removes the need for a cast.

importReact = require('react');

interface ITestState {
    selectedValue: string;
}

exportclassTestextendsReact.Component<{}, ITestState> {

    constructor() {
        super();
        this.state = { selectedValue: "A" };
    }

    change(event: React.FormEvent<HTMLSelectElement>) {
        // No longer need to cast to any - hooray for react!varsafeSearchTypeValue: string = event.currentTarget.value;

        console.log(safeSearchTypeValue); // in chrome => Bthis.setState({
            selectedValue: safeSearchTypeValue
        });
    }

    render() {
        return (
            <div><labelhtmlFor="searchType">Safe</label><selectclassName="form-control"id="searchType"onChange={e => this.change(e) } value={ this.state.selectedValue }>
                    <optionvalue="A">A</option><optionvalue="B">B</option></select><h1>{this.state.selectedValue}</h1></div>
        );
    }
}

Solution 3:

In my case onChange event was typed as React.ChangeEvent<HTMLSelectElement>:

onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
  console.warn('onChange TextInput value: ' + e.target.value);
}}

Solution 4:

Update: the official type-definitions for React have been including event types as generic types for some time now, so you now have full compile-time checking, and this answer is obsolete.


Is it possible to retrieve the value in a type-safe manner without casting to any?

Yes. If you are certain about the element your handler is attached to, you can do:

<select onChange={ e => this.selectChangeHandler(e) }>
    ...
</select>
private selectChangeHandler(e: React.FormEvent)
{
    var target = e.target as HTMLSelectElement;
    var intval: number = target.value; // Error: 'string' not assignable to 'number'
}

Live demo

The TypeScript compiler will allow this type-assertion, because an HTMLSelectElement is an EventTarget. After that, it should be type-safe, because you know that e.target is an HTMLSelectElement, because you just attached your event handler to it.

However, to guarantee type-safety (which, in this case, is relevant when refactoring), it is also needed to check the actual runtime-type:

if (!(target instanceofHTMLSelectElement))
{
    thrownewTypeError("Expected a HTMLSelectElement.");
}

Solution 5:

The easiest way is to add a type to the variable that is receiving the value, like this:

varvalue: string = (event.target as any).value;

Or you could cast the value property as well as event.target like this:

varvalue = ((event.target as any).valueasstring);

Edit:

Lastly, you can define what EventTarget.value is in a separate .d.ts file. However, the type will have to be compatible where it's used elsewhere, and you'll just end up using any again anyway.

globals.d.ts

interfaceEventTarget {
    value: any;
}

Post a Comment for "Typesafe Select Onchange Event Using Reactjs And Typescript"