打字稿输入onchange event.target.value


141

在我的react和typescript应用程序中,我使用:onChange={(e) => data.motto = (e.target as any).value}

我如何正确定义类的类型,这样我就不必用来绕过类型系统了any

export interface InputProps extends React.HTMLProps<Input> {
...

}

export class Input extends React.Component<InputProps, {}> {
}

如果我把target: { value: string };我得到:

ERROR in [default] /react-onsenui.d.ts:87:18
Interface 'InputProps' incorrectly extends interface 'HTMLProps<Input>'.
  Types of property 'target' are incompatible.
    Type '{ value: string; }' is not assignable to type 'string'.

Answers:


243

通常,事件处理程序应使用e.currentTarget.value,例如:

onChange = (e: React.FormEvent<HTMLInputElement>) => {
    const newValue = e.currentTarget.value;
}

您可以在这里阅读原因(还原“使SyntheticEvent.target通用,而不是SyntheticEvent.currentTarget。”)。

UPD:如@ roger-gusmao所述,它ChangeEvent更适合于键入表单事件。

onChange = (e: React.ChangeEvent<HTMLInputElement>)=> {
   const newValue = e.target.value;
}

17
这根本行不通。值不是接口EventTarget的属性
tocqueville

1
当然不是EventTarget,而是HTMLInputElement的一部分,您可以在这里看到完整的定义github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/…–
Yozi

1
哦,对不起,您曾经使用过currentTarget。在那种情况下,它是target
可行的

1
是的,您是对的,但正如github.com/DefinitelyTyped/DefinitelyTyped/pull/12239中所述,target在大多数情况下使用不正确。此外,目标不必T强迫我们正确书写
Yozi

1
这对我不起作用,我不得不将事件React.ChangeEvent<HTMLInputElement>强制转换为FormEvent。
Oblivionkey3

86

在TypeScript中使用的正确方法是

  handleChange(e: React.ChangeEvent<HTMLInputElement>) {
    // No longer need to cast to any - hooray for react!
    this.setState({temperature: e.target.value});
  }

  render() {
        ...
        <input value={temperature} onChange={this.handleChange} />
        ...
    );
  }

遵循完整的课程,最好了解一下:

import * as React from "react";

const scaleNames = {
  c: 'Celsius',
  f: 'Fahrenheit'
};


interface TemperatureState {
   temperature: string;
}

interface TemperatureProps {
   scale: string;

}

class TemperatureInput extends React.Component<TemperatureProps, TemperatureState> {
  constructor(props: TemperatureProps) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
    this.state = {temperature: ''};
  }

  //  handleChange(e: { target: { value: string; }; }) {
  //    this.setState({temperature: e.target.value});  
  //  }


  handleChange(e: React.ChangeEvent<HTMLInputElement>) {
    // No longer need to cast to any - hooray for react!
    this.setState({temperature: e.target.value});
  }

  render() {
    const temperature = this.state.temperature;
    const scale = this.props.scale;
    return (
      <fieldset>
        <legend>Enter temperature in {scaleNames[scale]}:</legend>
        <input value={temperature} onChange={this.handleChange} />
      </fieldset>
    );
  }
}

export default TemperatureInput;

3
注意:为了确保类型可供选择,添加lib: ["dom"]compilerOptionstsconfig.json
詹姆斯·康克林

1
@JamesConkling非常感谢!
亚历山大·里维斯特

1
如果您有多个输入,是否需要为每个输入一行?
Trevor Wood

确保在handleChange函数中适当分配了“ this”的另一种方法是将handleChange编写为箭头函数,即handleChange =(e:React.ChangeEvent <HTMLInputElement>)=> {this.setState(...); }; 这样一来,将不再需要使用构造函数来绑定handleEvent函数。
tlavarea

处理'this'而不是使用构造函数和bind方法的另一种方法是在onChange属性中使用箭头函数,即onChange = {e => this.handleChange(e)}
tlavarea


9

target你试图在添加InputProps是不一样的target,你想这是在React.FormEvent

因此,我可以提出的解决方案是,扩展与事件相关的类型以添加​​目标类型,如下所示:

interface MyEventTarget extends EventTarget {
    value: string
}

interface MyFormEvent<T> extends React.FormEvent<T> {
    target: MyEventTarget
}

interface InputProps extends React.HTMLProps<Input> {
    onChange?: React.EventHandler<MyFormEvent<Input>>;
}

一旦有了这些类,就可以将输入组件用作

<Input onChange={e => alert(e.target.value)} />

没有编译错误。实际上,您还可以将上面的前两个接口用于其他组件。


值类型不是字符串!
罗格·古斯芒

7

幸运的是我找到了解决方案。您可以

从'react'导入{ChangeEvent};

然后编写如下代码: e:ChangeEvent<HTMLInputElement>


2

这是一种经过TS 3.3测试的ES6对象分解的方法。
此示例用于文本输入。

name: string = '';

private updateName({ target }: { target: HTMLInputElement }) {
    this.name = target.value;
}

1

这是在使用FileList对象时:

onChange={(event: React.ChangeEvent<HTMLInputElement>): void => {
  const fileListObj: FileList | null = event.target.files;
  if (Object.keys(fileListObj as Object).length > 3) {
    alert('Only three images pleaseeeee :)');
  } else {
    // Do something
  }

  return;
}}

1
  function handle_change(
    evt: React.ChangeEvent<HTMLInputElement>
  ): string {
    evt.persist(); // This is needed so you can actually get the currentTarget
    const inputValue = evt.currentTarget.value;

    return inputValue
  }

并确保你有"lib": ["dom"]你的tsconfig


1

当使用子组件时,我们检查像这样的类型。

父组件:

export default () => {

  const onChangeHandler = ((e: React.ChangeEvent<HTMLInputElement>): void => {
    console.log(e.currentTarget.value)
  }

  return (
    <div>
      <Input onChange={onChangeHandler} />
    </div>
  );
}

子组件:

type Props = {
  onChange: (e: React.ChangeEvent<HTMLInputElement>) => void
}

export Input:React.FC<Props> ({onChange}) => (
  <input type="tex" onChange={onChange} />
)

0

尚未提及的替代方法是键入onChange函数而不是其接收的prop。使用React.ChangeEventHandler:

const stateChange: React.ChangeEventHandler<HTMLInputElement> = (event) => {
    console.log(event.target.value);
};

-1

谢谢@haind

HTMLInputElement适用于输入字段

//Example
var elem = e.currentTarget as HTMLInputElement;
elem.setAttribute('my-attribute','my value');
elem.value='5';

HTMLInputElement是接口的继承,HTMLElement而接口是从EventTarget根级别继承的。因此,我们可以断言使用as算子根据上下文使用特定的接口,例如在这种情况下,我们将HTMLInputElement其他接口用于输入字段HTMLButtonElementHTMLImageElement等等。

https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLInputElement

有关更多参考,您可以在此处检查其他可用接口

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.