Javascript typesafe 使用 reactjs 和 typescript 选择 onChange 事件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/33256274/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
typesafe select onChange event using reactjs and typescript
提问by davestevens
I have figured out how to tie up an event handler on a SELECT element using an ugly cast of the event to any.
我已经想出了如何使用一个丑陋的事件转换到 any 来绑定一个 SELECT 元素上的事件处理程序。
Is it possible to retrieve the value in a type-safe manner without casting to any?
是否可以以类型安全的方式检索值而不强制转换为任何值?
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>
);
}
}
采纳答案by davestevens
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.
由于将我的类型升级为 react 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>
);
}
}
回答by Sergei Basharov
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:
我尝试使用React.FormEvent<HTMLSelectElement>
但它导致编辑器中出现错误,即使EventTarget
代码中没有可见:
The property 'value' does not exist on value of type 'EventTarget'
“EventTarget”类型的值上不存在属性“value”
Then I changed React.FormEvent
to React.ChangeEvent
and it helped:
然后,我改变React.FormEvent
到React.ChangeEvent
它帮助:
private changeName(event: React.ChangeEvent<HTMLSelectElement>) {
event.preventDefault();
this.props.actions.changeName(event.target.value);
}
回答by John Weisz
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.
更新:React 的官方类型定义已经包含事件类型作为泛型类型已有一段时间了,所以你现在有完整的编译时检查,这个答案已经过时了。
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'
}
The TypeScript compiler will allow this type-assertion, because an HTMLSelectElementis an EventTarget. After that, it should be type-safe, because you know that e.targetis an HTMLSelectElement, because you just attached your event handler to it.
TypeScript 编译器将允许这种类型断言,因为HTMLSelectElement是一个EventTarget。之后,它应该是类型安全的,因为您知道e.target是一个HTMLSelectElement,因为您刚刚将事件处理程序附加到它。
However, to guaranteetype-safety (which, in this case, is relevant when refactoring), it is also needed to check the actual runtime-type:
然而,为了保证类型安全(在这种情况下,在重构时是相关的),还需要检查实际的运行时类型:
if (!(target instanceof HTMLSelectElement))
{
throw new TypeError("Expected a HTMLSelectElement.");
}
回答by thoughtrepo
The easiest way is to add a type to the variable that is receiving the value, like this:
最简单的方法是向接收值的变量添加一个类型,如下所示:
var value: string = (event.target as any).value;
Or you could cast the value
property as well as event.target
like this:
或者你可以像这样投射value
属性event.target
:
var value = ((event.target as any).value as string);
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.
最后,您可以定义EventTarget.value
单独.d.ts
文件中的内容。但是,该类型必须与在其他地方使用的地方兼容,any
无论如何您最终都会再次使用。
globals.d.ts
globals.d.ts
interface EventTarget {
value: any;
}
回答by Петр Графинов
it works:
有用:
type HtmlEvent = React.ChangeEvent<HTMLSelectElement>
const onChange: React.EventHandler<HtmlEvent> =
(event: HtmlEvent) => {
console.log(event.target.value)
}
回答by Hymankobec
In my case onChange event was typed as React.ChangeEvent:
在我的例子中,onChange 事件被输入为 React.ChangeEvent:
onChange={ (e: React.ChangeEvent<HTMLSelectElement>) => {
console.warn('onChange TextInput value: ' + e.target.value);
}
}
回答by Marco Lackovic
JSX:
JSX:
<select value={ this.state.foo } onChange={this.handleFooChange}>
<option value="A">A</option>
<option value="B">B</option>
</select>
TypeScript:
打字稿:
private handleFooChange = (event: React.FormEvent<HTMLSelectElement>) => {
const element = event.target as HTMLSelectElement;
this.setState({ foo: element.value });
}
回答by davestevens
As far as I can tell, this is currently not possible - a cast is always needed.
据我所知,目前这是不可能的 - 总是需要演员阵容。
To make it possible, the .d.ts of react would need to be modified so that the signature of the onChange of a SELECT element used a new SelectFormEvent. The new event type would expose target, which exposes value. Then the code could be typesafe.
为了使其成为可能,需要修改 react 的 .d.ts,以便 SELECT 元素的 onChange 签名使用新的 SelectFormEvent。新的事件类型将公开目标,从而公开值。然后代码可以是类型安全的。
Otherwise there will always be the need for a cast to any.
否则总是需要演员阵容。
I could encapsulate all that in a MYSELECT tag.
我可以将所有这些都封装在一个 MYSELECT 标签中。
回答by Artru
In addition to @thoughtrepo's answer:
除了@thoughtrepo 的回答:
Until we do not have definitely typed events in React it might be useful to have a special target interface for input controls:
除非我们在 React 中没有明确键入的事件,否则为输入控件提供一个特殊的目标接口可能会很有用:
export interface FormControlEventTarget extends EventTarget{
value: string;
}
And then in your code cast to this type where is appropriate to have IntelliSensesupport:
然后在您的代码中转换为这种类型的适合具有 IntelliSense支持的位置:
import {FormControlEventTarget} from "your.helper.library"
(event.target as FormControlEventTarget).value;