typesafe使用reactjs和typescript选择onChange事件

dav*_*ens 53 javascript typescript reactjs

我已经想出如何使用事件的丑陋演员来绑定SELECT元素上的事件处理程序.

是否可以以类型安全的方式检索值而不转换为任何值?

import React = require('react');

interface ITestState {
    selectedValue: string;
}

export class Test extends React.Component<{}, ITestState> {

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

    change(event: React.FormEvent) {
        console.log("Test.change");
        console.log(event.target); // in chrome => <select class="form-control" id="searchType" data-reactid=".0.0.0.0.3.1">...</select>

        // Use cast to any works but is not type safe
        var unsafeSearchTypeValue = ((event.target) as any).value;

        console.log(unsafeSearchTypeValue); // in chrome => B

        this.setState({
            selectedValue: unsafeSearchTypeValue
        });
    }

    render() {
        return (
            <div>
                <label htmlFor="searchType">Safe</label>
                <select className="form-control" id="searchType" onChange={ e => this.change(e) } value={ this.state.selectedValue }>
                    <option value="A">A</option>
                    <option value="B">B</option>
                </select>
                <h1>{this.state.selectedValue}</h1>
            </div>
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

dav*_*ens 55

由于升级我的打字以反应0.14.43(我不确定何时引入它),React.FormEvent类型现在是通用的,这消除了对转换的需要.

import React = require('react');

interface ITestState {
    selectedValue: string;
}

export class Test extends React.Component<{}, ITestState> {

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

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

        console.log(safeSearchTypeValue); // in chrome => B

        this.setState({
            selectedValue: safeSearchTypeValue
        });
    }

    render() {
        return (
            <div>
                <label htmlFor="searchType">Safe</label>
                <select className="form-control" id="searchType" onChange={ e => this.change(e) } value={ this.state.selectedValue }>
                    <option value="A">A</option>
                    <option value="B">B</option>
                </select>
                <h1>{this.state.selectedValue}</h1>
            </div>
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 截至2016年12月,必须使用`event.currentTarget.value`从表单中获取数据. (14认同)
  • 我已编辑@MartinMajewski以使用currentTarget(http://joequery.me/code/event-target-vs-event-currenttarget-30-seconds/是一个很好的解释) (2认同)

Ser*_*rov 45

我尝试使用React.FormEvent<HTMLSelectElement>但它导致编辑器出错,即使EventTarget代码中没有可见:

'EventTarget'类型的值不存在属性'value'

然后,我改变React.FormEventReact.ChangeEvent它帮助:

private changeName(event: React.ChangeEvent<HTMLSelectElement>) {
    event.preventDefault();
    this.props.actions.changeName(event.target.value);
}
Run Code Online (Sandbox Code Playgroud)

  • 这应该是最简单的方法,如果我访问e.target.value,FormEvent总是显示错误 (3认同)

Joh*_*isz 11

更新:React的官方类型定义已经将事件类型作为泛型类型包含了一段时间,因此您现在有完整的编译时检查,这个答案已经过时了.


是否可以以类型安全的方式检索值而不转换为任何值?

是.如果您确定您的处理程序所附加的元素,您可以执行以下操作:

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

现场演示

TypeScript编译器将允许此类型断言,因为HTMLSelectElementEventTarget.之后,它应该是类型安全的,因为您知道e.target是一个HTMLSelectElement,因为您只是将事件处理程序附加到它.

但是,为了保证类型安全(在这种情况下,在重构时相关),还需要检查实际的运行时类型:

if (!(target instanceof HTMLSelectElement))
{
    throw new TypeError("Expected a HTMLSelectElement.");
}
Run Code Online (Sandbox Code Playgroud)


Jac*_*bec 10

在我的情况下,onChange事件输入为React.ChangeEvent<HTMLSelectElement>

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


tho*_*epo 8

最简单的方法是向接收值的变量添加一个类型,如下所示:

var value: string = (event.target as any).value;
Run Code Online (Sandbox Code Playgroud)

或者您可以像以下一样投射该value属性event.target:

var value = ((event.target as any).value as string);
Run Code Online (Sandbox Code Playgroud)

编辑:

最后,您可以定义EventTarget.value单独.d.ts文件中的内容.但是,该类型必须与其他地方使用的类型兼容,并且您最终any还是会再次使用.

globals.d.ts

interface EventTarget {
    value: any;
}
Run Code Online (Sandbox Code Playgroud)

  • 我希望完全摆脱“as any”演员阵容。 (4认同)

小智 7

有用:

type HtmlEvent = React.ChangeEvent<HTMLSelectElement>

const onChange: React.EventHandler<HtmlEvent> = 
   (event: HtmlEvent) => { 
       console.log(event.target.value) 
   }
Run Code Online (Sandbox Code Playgroud)


Mar*_*vic 5

JSX :

<select value={ this.state.foo } onChange={ this.handleFooChange }>
    <option value="A">A</option>
    <option value="B">B</option>
</select>
Run Code Online (Sandbox Code Playgroud)

打字稿

private handleFooChange = (event: React.FormEvent<HTMLSelectElement>) => {
    const element = event.target as HTMLSelectElement;
    this.setState({ foo: element.value });
}
Run Code Online (Sandbox Code Playgroud)