source

typesafe 선택 onreactjs 및 typescript를 사용하여 이벤트 변경

topadmin 2023. 2. 15. 21:58

typesafe 선택 onreactjs 및 typescript를 사용하여 이벤트 변경

이벤트의 추악한 캐스트를 사용하여 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>
        );
    }
}

나는 그것을 사용해봤어요.React.FormEvent<HTMLSelectElement>에디터에서 오류가 발생하였습니다.이러한 오류는 없습니다.EventTarget코드에 표시됨:

'EventTarget' 형식의 값에 'value' 속성이 없습니다.

그때 나는 변했다.React.FormEvent로.React.ChangeEvent도움이 되었습니다.

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

입력 내용을 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>
        );
    }
}

저 같은 경우에는onChange이벤트는 다음과 같이 입력되었습니다.React.ChangeEvent<HTMLSelectElement>:

onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
  console.warn('onChange TextInput value: ' + e.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'
}

라이브 데모

HTMLSelectElementEventTarget이기 때문에 TypeScript 컴파일러는 이 타입 어사션을 허용합니다.그 후에는 e.targetHTMLSelectElement라는 을 알고 있기 때문에 이벤트핸들러를 접속했을 뿐입니다.

그러나 유형 안전을 보장하기 위해(이 경우 리팩터링 시 관련됨), 실제 런타임 유형을 확인해야 합니다.

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);

편집:

마지막으로 무엇을 정의할 수 있습니다.EventTarget.value별매.d.ts단, 타입은 다른 곳에서 사용되는 경우 호환성이 있어야 합니다.그러면 이 타입을 사용할 수 있습니다.any어쨌든 다시.

글로벌

interface EventTarget {
    value: any;
}

동작:

type HtmlEvent = React.ChangeEvent<HTMLSelectElement>

const onChange: React.EventHandler<HtmlEvent> = 
   (event: HtmlEvent) => { 
       console.log(event.target.value) 
   }

JSX:

<select value={ this.state.foo } onChange={ this.handleFooChange }>
    <option value="A">A</option>
    <option value="B">B</option>
</select>

Type Script:

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

내가 아는 한, 이것은 현재 가능하지 않다. - 항상 깁스가 필요하다.

그러기 위해서는 SELECT 요소의 onChange 시그니처가 새로운 SelectFormEvent를 사용하도록 react의 .d.ts를 변경해야 합니다.새 이벤트 유형은 대상을 노출하여 값을 노출합니다.그럼 암호는 타이프세이프일 수도 있겠네요

그렇지 않으면 항상 어떤 사람에게도 캐스팅이 필요할 것입니다.

이 모든 것을 MYSELECT 태그에 캡슐화할 수 있습니다.

@thoughtrepo의 답변과 더불어:

React에 이벤트를 확실히 입력하지 않는 한 입력 컨트롤에 대한 특별한 대상 인터페이스를 사용하는 것이 유용할 수 있습니다.

export interface FormControlEventTarget extends EventTarget{
    value: string;
}

다음으로 IntelliSense를 지원하기에 적합한 다음 유형의 코드를 입력합니다.

 import {FormControlEventTarget} from "your.helper.library"

 (event.target as FormControlEventTarget).value;

언급URL : https://stackoverflow.com/questions/33256274/typesafe-select-onchange-event-using-reactjs-and-typescript