イベントのanyいキャストをanyに使用して、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>
);
}
}
タイピングをアップグレードして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>
);
}
}
React.FormEvent<HTMLSelectElement>
を使用しようとしましたが、コードにEventTarget
が表示されていなくても、エディターでエラーが発生しました。
プロパティ 'value'は、タイプ 'EventTarget'の値には存在しません
次に、React.FormEvent
をReact.ChangeEvent
に変更しました。
private changeName(event: React.ChangeEvent<HTMLSelectElement>) {
event.preventDefault();
this.props.actions.changeName(event.target.value);
}
更新:Reactの公式の型定義には、しばらくの間、ジェネリック型としてイベント型が含まれているため、コンパイル時の完全なチェックが可能になり、この回答は廃止されました。
型に安全な方法で値を取得することはできますか?
はい。ハンドラーがアタッチされている要素について確信がある場合は、次のことができます。
<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'
}
HTMLSelectElementはEventTargetであるため、TypeScriptコンパイラはこのタイプアサーションを許可します。その後、e.targetがHTMLSelectElementであることがわかっているため、タイプセーフになるはずです。イベントハンドラー。
ただし、guaranteetype-safety(この場合、リファクタリング時に関連する)には、実際のruntime-typeを確認する必要もあります。
if (!(target instanceof HTMLSelectElement))
{
throw new TypeError("Expected a HTMLSelectElement.");
}
最も簡単な方法は、次のように、値を受け取る変数に型を追加することです。
var value: string = (event.target as any).value;
または、次のようにvalue
プロパティとevent.target
をキャストできます。
var value = ((event.target as any).value as string);
Edit:
最後に、EventTarget.value
が別の.d.ts
ファイルにあるものを定義できます。ただし、他の場所で使用される場合は、型に互換性がなければならず、とにかくany
を再び使用することになります。
globals.d.ts
interface EventTarget {
value: any;
}
できます:
type HtmlEvent = React.ChangeEvent<HTMLSelectElement>
const onChange: React.EventHandler<HtmlEvent> =
(event: HtmlEvent) => {
console.log(event.target.value)
}
私が知る限り、これは現在不可能です-キャストが常に必要です。
それを可能にするには、reactの.d.tsを変更して、SELECT要素のonChangeのシグネチャが新しいSelectFormEventを使用するようにする必要があります。新しいイベントタイプは、値を公開するターゲットを公開します。その場合、コードはタイプセーフになります。
そうしないと、常にanyへのキャストが必要になります。
これらすべてをMYSELECTタグにカプセル化できます。
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 });
}
私の場合、onChangeイベントはReact.ChangeEventと入力されました。
onChange={ (e: React.ChangeEvent<HTMLSelectElement>) => {
console.warn('onChange TextInput value: ' + e.target.value);
}
}
@thoughtrepoの答えに加えて:
Reactにイベントを確実に入力しない限り、入力コントロール用の特別なターゲットインターフェイスを使用すると便利です。
export interface FormControlEventTarget extends EventTarget{
value: string;
}
そして、このタイプにキャストするコードでIntelliSenseをサポートするのに適しています:
import {FormControlEventTarget} from "your.helper.library"
(event.target as FormControlEventTarget).value;