使用 MaterialUI 和 Typescript 在 React 中传递给 onKeyPressed 函数的事件的正确类型是啥?
Posted
技术标签:
【中文标题】使用 MaterialUI 和 Typescript 在 React 中传递给 onKeyPressed 函数的事件的正确类型是啥?【英文标题】:Which is the right type for an event passed to the onKeyPressed function in React with MaterialUI and Typescript?使用 MaterialUI 和 Typescript 在 React 中传递给 onKeyPressed 函数的事件的正确类型是什么? 【发布时间】:2021-05-30 23:08:33 【问题描述】:在我使用 Typescript 和 MaterialUI 的 React 应用程序中,我有一个 TextField。
我想在按下enter
时访问input
html 元素值。
所以我有以下代码
const keyPress = (e: any) =>
if (e.key === "Enter")
console.log("Do login", e.target.value);
;
在返回的 React 树的某个地方我有这个
<TextField onKeyPress=keyPress />
此代码有效,但我的问题是我不明白如何为传递给函数 keyPressed
的事件 e
定义正确的类型。
根据 VSCode intellisense 在我将鼠标悬停在 onKeyPress
道具上时的建议,我知道我应该使用 KeyboardEvent<HTMLDivElement>
,但问题是我收到一个错误,上面写着 Type 'KeyboardEvent' is not generic
。
我做错了什么?
顺便说一句,如果我将事件类型设为 e: key: string; target: any
,一切都会正常工作,但是当我尝试遵循正确的方式时,了解我做错了什么仍然很有趣。
更新
经过更多研究,似乎传递给keyPressed
函数的事件是KeyboardEvent
类型,它的target
属性是EventTarget
类型。
查看global.d.ts
在React
包中的EventTarget
的定义,然后发现是空接口。
在global.d.ts
的 cmets 中,我还读到“警告:所有这些接口都是空的。如果您想要各种属性的类型定义
(比如HTMLInputElement.prototype.value),你需要添加--lib DOM
(通过命令行或者tsconfig.json)。但是我的tsconfig.json
实际上在库中包含DOM
(属性是"lib": ["dom", "dom.iterable", "esnext"],
) .
同样,我可以让事情正常进行,但我想了解如何为该事件获取干净的类型。
【问题讨论】:
您可以在编辑器中通过在onKeyPress
属性上执行CTRL+click
直接看到这一点,这将带您进入material-ui 的*.d.ts
文件。
@Ajeet Shah 感谢您的回复,但您的建议并不那么简单,至少对我而言。 onKeyPress
的类型为 KeyboardEventHandler<T>
。如果我查看KeyboardEventHandler<T>
,我发现它被定义为EventHandler<KeyboardEvent<T>>
。然后我查看EventHandler<KeyboardEvent<T>>
,它被定义为EventHandler<E extends SyntheticEvent<any>> = bivarianceHack(event: E): void ["bivarianceHack"];
。现在事情对我来说变得有点复杂了。最终结果是我无法为传递给keyPress
函数的事件提供一个干净的类型。
【参考方案1】:
您可以将onKeyPress
处理程序的类型定义为:keyPress
:
import KeyboardEvent, EventHandler from 'react'
const keyPress: EventHandler<KeyboardEvent<HTMLInputElement>> = (e) =>
if (e.key === 'Enter')
console.log('Do login', (e.target as HTMLInputElement).value)
<TextField id="id" label="Name" onKeyPress=keyPress />
Typescript 会给你以下错误...
“EventTarget”类型上不存在属性“值”。
关于这个错误的另一个帖子:Property 'value' does not exist on type EventTarget in TypeScript
...当您访问值时 - e.target.value
尽管存在 value
,因此您可以通过将其转换为 HTMLInputElement
来抑制此错误,如上所示。
在我看来,您正在尝试访问e.key
,而不是onKeyPress
处理程序中的e.target.value
;因为您最有可能在 onChange
处理程序中这样做。
相同,但形式可能更短:
type KeyPressType<T = Element> = EventHandler<KeyboardEvent<T>>
const keyPress: KeyPressType<HTMLInputElement> = (e) =>
if (e.key === 'Enter')
console.log('Do login', (e.target as HTMLInputElement).value)
问题:e
的类型是什么?
答案:是KeyboardEvent<HTMLInputElement>
【讨论】:
以上是关于使用 MaterialUI 和 Typescript 在 React 中传递给 onKeyPressed 函数的事件的正确类型是啥?的主要内容,如果未能解决你的问题,请参考以下文章
Springboot + mybatis + React+redux+React-router+antd+Typescript: React+Typescrip项目的搭建
React 和 MaterialUI - 使用论文的 GridLayout
使用 MaterialUI 和 Typescript 在 React 中传递给 onKeyPressed 函数的事件的正确类型是啥?