Typescript: React事件类型

React事件的正确类型是什么?最初为了简单起见,我只使用any。现在,我试图清理事情,并完全避免使用any

简单的形式是这样的:

export interface LoginProps {
login: {
[k: string]: string | Function
uname: string
passw: string
logIn: Function
}
}
@inject('login') @observer
export class Login extends Component<LoginProps, {}> {
update = (e: React.SyntheticEvent<EventTarget>): void => {
this.props.login[e.target.name] = e.target.value
}
submit = (e: any): void => {
this.props.login.logIn()
e.preventDefault()
}
render() {
const { uname, passw } = this.props.login
return (
<div id='login' >
<form>
<input
placeholder='Username'
type="text"
name='uname'
value={uname}
onChange={this.update}
/>
<input
placeholder='Password'
type="password"
name='passw'
value={passw}
onChange={this.update}
/>
<button type="submit" onClick={this.submit} >
Submit
</button>
</form>
</div>
)
}
}

我在这里使用什么类型作为事件类型?

React.SyntheticEvent<EventTarget>似乎没有工作,因为我得到一个错误,namevaluetarget上不存在。

对所有事件的更普遍的答案将真的很感激。

谢谢

448482 次浏览

问题不在于Event类型,而在于typescript中的EventTarget接口只有3个方法:

interface EventTarget {
addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
dispatchEvent(evt: Event): boolean;
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
}


interface SyntheticEvent {
bubbles: boolean;
cancelable: boolean;
currentTarget: EventTarget;
defaultPrevented: boolean;
eventPhase: number;
isTrusted: boolean;
nativeEvent: Event;
preventDefault(): void;
stopPropagation(): void;
target: EventTarget;
timeStamp: Date;
type: string;
}

因此,namevalue在EventTarget上不存在是正确的。您需要做的是将目标转换为具有所需属性的特定元素类型。在本例中,它将是HTMLInputElement

update = (e: React.SyntheticEvent): void => {
let target = e.target as HTMLInputElement;
this.props.login[target.name] = target.value;
}

同样适用于事件而不是React。synticevent,你也可以输入它们如下:EventMouseEventKeyboardEvent…等等,取决于处理程序的用例。

查看所有这些类型定义的最佳方法是签出.d。Ts文件来自typescript &反应。

也可以点击下面的链接了解更多解释: 为什么是事件。目标不是元素在Typescript? < / p >

SyntheticEvent接口是通用的:

interface SyntheticEvent<T> {
...
currentTarget: EventTarget & T;
...
}

(从技术上讲,currentTarget属性位于父类型BaseSyntheticEvent上。)

currentTarget是泛型约束和EventTarget的交集。
此外,由于你的事件是由输入元素引起的,你应该使用ChangeEvent (在定义文件中react文档).

应该是:

update = (e: React.ChangeEvent<HTMLInputElement>): void => {
this.props.login[e.currentTarget.name] = e.currentTarget.value
}

(注意:这个答案最初建议使用React.FormEvent。评论中的讨论与这个建议有关,但React.ChangeEvent应该如上所示使用。)

结合Nitzan和Edwin的回答,我发现这样的东西对我很有用:

update = (e: React.FormEvent<EventTarget>): void => {
let target = e.target as HTMLInputElement;
this.props.login[target.name] = target.value;
}

我认为最简单的方法是:

type InputEvent = React.ChangeEvent<HTMLInputElement>;
type ButtonEvent = React.MouseEvent<HTMLButtonElement>;


update = (e: InputEvent): void => this.props.login[e.target.name] = e.target.value;
submit = (e:  ButtonEvent): void => {
this.props.login.logIn();
e.preventDefault();
}

你可以在react中这样做

handleEvent = (e: React.SyntheticEvent<EventTarget>) => {
const simpleInput = (e.target as HTMLInputElement).value;
//for simple html input values
const formInput = (e.target as HTMLFormElement).files[0];
//for html form elements
}

对于那些正在寻找一个解决方案来获取事件和存储一些东西,在我的情况下,HTML 5元素,在useState上,这里是我的解决方案:

const [anchorElement, setAnchorElement] = useState<HTMLButtonElement | null>(null);


const handleMenu = (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) : void => {
setAnchorElement(event.currentTarget);
};

我在一个types.ts文件中有以下html输入,选择和文本区域:

export type InputChangeEventHandler = React.ChangeEventHandler<HTMLInputElement>
export type TextareaChangeEventHandler = React.ChangeEventHandler<HTMLTextAreaElement>
export type SelectChangeEventHandler = React.ChangeEventHandler<HTMLSelectElement>

然后导入它们:

import { InputChangeEventHandler } from '../types'

然后使用它们:


const updateName: InputChangeEventHandler = (event) => {
// Do something with `event.currentTarget.value`
}
const updateBio: TextareaChangeEventHandler = (event) => {
// Do something with `event.currentTarget.value`
}
const updateSize: SelectChangeEventHandler = (event) => {
// Do something with `event.currentTarget.value`
}

然后在标记上应用函数(用其他必要的道具替换...):

<input onChange={updateName} ... />
<textarea onChange={updateName} ... />
<select onChange={updateSize} ... >
// ...
</select>

for update: event: React.ChangeEvent 用于提交:event: React.FormEvent event: React.MouseEvent

以下有相同的类型:

let event1: { target: { value: any } };
let event2: { target: HTMLInputElement } };

这是2022年typescript编译器的推荐方式:

const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
console.log('click');
};

不需要添加void作为返回值,因为这是由编译器自动完成的。

或者你可以用

const handles = (e: React.UIEvent<'type of element', UIEvent>) => {
//do something
}