ChatGPT解决这个技术问题 Extra ChatGPT

打字稿输入 onchange event.target.value

在我的反应和打字稿应用程序中,我使用:

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'.

S
Silicum Silium

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

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

您可以在此处阅读原因 (Revert "Make SyntheticEvent.target generic, not SyntheticEvent.currentTarget.")。

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

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

这根本行不通。 value 不是接口 EventTarget 的属性
当然不是 EventTarget,而是 HTMLInputElement 的一部分您可以在此处查看完整定义github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/…
哦,抱歉,您使用了 currentTarget。在这种情况下,是的,它有效,但问题是关于 target
是的,您是对的,但如 github.com/DefinitelyTyped/DefinitelyTyped/pull/12239 中所述,在大多数情况下使用 target 是不正确的。此外,target 没有 T 来强制我们正确写入
这对我不起作用,我不得不将事件转换为 React.ChangeEvent<HTMLInputElement> 而不是 FormEvent。
R
Roger Gusmao

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

注意:为确保类型可用,请将 lib: ["dom"] 添加到 tsconfig.json 中的 compilerOptions
@JamesConkling 非常感谢!
如果你有多个输入,你需要为每个输入一行吗?
确保在 handleChange 函数中正确分配“this”的另一种方法是将 handleChange 编写为箭头函数,即 handleChange = (e: React.ChangeEvent) => { this.setState(...); };通过这样做,将不再需要使用构造函数来绑定 handleEvent 函数。
另一种处理“this”而不是使用构造函数和绑定方法的方法是使用 onChange 属性中的箭头函数,即 onChange={e => this.handleChange(e)}
K
KyleMit

您可以执行以下操作:

import { ChangeEvent } from 'react';

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

h
haind

as HTMLInputElement 适合我


那没有.target
N
Nawaraj Jaishi

我们还可以使用定义类型(在功能组件中)的 onChange 事件触发,如下所示:

 const handleChange = (
    e: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>
  ) => {
        const name = e.target.name;
        const value = e.target.value;
};


L
Leone

您尝试在 InputProps 中添加的 target 与您想要的 React.FormEvent 中的 target 不同

所以,我能想出的解决方案是,扩展事件相关类型以添加您的目标类型,如:

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)} />

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


值类型不是字符串!
S
Sergey Ivchenko

我使用这样的东西:

import { ChangeEvent, useState } from 'react';


export const InputChange = () => {
  const [state, setState] = useState({ value: '' });

  const handleChange = (event: ChangeEvent<{ value: string }>) => {
    setState({ value: event?.currentTarget?.value });
  }
  return (
    <div>
      <input onChange={handleChange} />
      <p>{state?.value}</p>
    </div>
  );
}

终于有些东西奏效了。我仍然不明白 ChangeEvent 如何在 currentTarger 或 target 上没有值...
E
Ericgit

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

父组件:

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} />
)

微小的编辑删除多余的括号 - const onChangeHandler = (e: React.ChangeEvent): void => {
f
fjplaurr

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

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

a
anni

这是使用 TS 3.3 测试的 ES6 对象解构方法。此示例用于文本输入。

name: string = '';

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

这是一个很好的答案,适用于所有领域。我对 Angular 很感兴趣,被迫使用 React 一年,现在我又在玩 Angular 以保持新鲜感。 React 提供了一些 Typescript 原生缺乏的非常好的事件接口。这种方法有助于获得相同的所需类型,即使在原版中也是如此。谢谢。
D
Dryden Williams

这是当您使用 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;
}}

A
Ali Jamal

谢谢@haind

HTMLInputElement 适用于输入字段

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

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

https://i.stack.imgur.com/cp3xo.png

如需更多参考,您可以在此处查看其他可用接口

Mozilla 的 Web API 接口

Microsoft 外部节点模块中的接口


I
Isaac Alencar de Olivera

如果您这样做,则无需键入:

<input onChange={(event) => { setValue(e.target.value) }} />

因为如果你直接在 html 标签中用箭头函数设置一个新值,typescript 默认会理解事件的类型。


S
Suraj Rao

ChangeEvent<HTMLInputElement> 是 typescript 中更改事件的类型。就是这样完成的——

import { ChangeEvent } from 'react';

const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => {
    setValue(event.target.value);
};

a
avalanche1
  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
  }

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


m
mehari

这对我有用,它也与框架无关。

const handler = (evt: Event) => {
  console.log((evt.target as HTMLInputElement).value))
}

K
Keshav Gera
import { NativeSyntheticEvent, TextInputChangeEventData,} from 'react-native';



  // Todo in java script
 const onChangeTextPassword = (text : any) => {
    setPassword(text);
  }
    

// 类型脚本中的 Todo 使用 this

  const onChangeTextEmail = ({ nativeEvent: { text },}: NativeSyntheticEvent<TextInputChangeEventData>) => {
    console.log("________ onChangeTextEmail _________ "+ text);
    setEmailId(text);
  };


 <TextInput
          style={{ width: '100%', borderBottomWidth: 1, borderBottomColor: 'grey', height: 40, }}
          autoCapitalize="none"
          returnKeyType="next"
          maxLength={50}
          secureTextEntry={false}
          onChange={onChangeTextEmail}
          value={emailId}
          defaultValue={emailId}
          
        />