正文从这开始~
总览
在React中,当我们试图访问类型为HTMLElement
的元素上不存在的属性时,就会发生Property 'X' does not exist on type 'HTMLElement'错误。为了解决该错误,在访问属性之前,使用类型断言来正确地类型声明元素。
文章图片
这里有三个例子来展示错误是如何发生的。
// App.tsximport {useEffect} from 'react';
export default function App() {
useEffect(() => {
const input = document.getElementById('first_name');
// ?? Property 'value' does not exist on type 'HTMLElement'.ts(2339)
console.log(input?.value);
// -----------------------------------------------------------------const link = document.getElementById('link');
// ?? Property 'href' does not exist on type 'HTMLElement'.ts(2339)
console.log(link?.href);
// -----------------------------------------------------------------const button = document.getElementById('btn');
if (button != null) {
// ?? Property 'disabled' does not exist on type 'HTMLElement'.ts(2339)
button.disabled = true;
}
}, []);
return (" target="_blank" rel="noreferrer">
Open Google);
}
产生错误的原因是,
document.getElementById
方法的返回类型是HTMLElement | null
,但是我们试图访问的属性不存在于HTMLElement
类型。类型断言 为了解决这个错误,使用类型断言来为元素正确地进行类型声明。比如说,类型断言为
HTMLInputElement
, HTMLButtonElement
, HTMLAnchorElement
, HTMLImageElement
, HTMLDivElement
, HTMLTextAreaElement
等等。这取决于你所处理的元素。这些类型始终命名为
HTML***Element
。一旦你开始输入HTML…
,你的IDE将会帮你自动补全。import {useEffect} from 'react';
export default function App() {
useEffect(() => {
// ? type elements correctly via type assertions
const input = document.getElementById('first_name') as HTMLInputElement;
console.log(input?.value);
const link = document.getElementById('link') as HTMLAnchorElement;
console.log(link?.href);
const button = document.getElementById('btn') as HTMLButtonElement;
if (button != null) {
button.disabled = true;
}
}, []);
return (" target="_blank" rel="noreferrer">
Open Google);
}
类型断言被用于我们知道值的类型信息,但是TypeScript却不知道的时候。
我们明确的告诉TypeScript,【React报错之Property 'X' does not exist on type 'HTMLElement'】同样的,我们将input
变量上存储了HTMLInputElement
,并让TS不要担心。
link
变量类型声明为HTMLAnchorElement
,将btn
变量类型声明为HTMLButtonElement
。你可以在访问一个属性之前,内联使用类型断言。
import {useEffect} from 'react';
export default function App() {
useEffect(() => {
const value = https://www.it610.com/article/(document.getElementById('first_name') as HTMLInputElement).value;
console.log(value);
}, []);
return (" target="_blank" rel="noreferrer">
Open Google);
}
如果你只需要访问属性一次,并且不希望将元素分配给变量,那么内联类型声明可以完成这项工作。
如果你想更精确地处理元素的类型,可以使用联合类型将类型声明为
HTML***Element | null
。import {useEffect} from 'react';
export default function App() {
useEffect(() => {
const input = document.getElementById(
'first_name',
) as HTMLInputElement | null;
console.log(input?.value);
const link = document.getElementById('link') as HTMLAnchorElement | null;
console.log(link?.href);
const button = document.getElementById('btn') as HTMLButtonElement | null;
if (button != null) {
button.disabled = true;
}
}, []);
return (" target="_blank" rel="noreferrer">
Open Google);
}
HTML***Element
或者null
类型是最准确的类型,因为如果DOM元素上不存在id
属性,那么document.getElementById()
将会返回null
。你可以使用可选链操作符(
?.
)在访问属性之前来进行短路运算,如果引用是空值(null
或者undefined
)的话。或者,你可以使用简单的
if
语句作为类型守卫,就像我们对button
处理的那样。总结 最佳实践是在类型断言中包含
null
。因为如果元素上面不提供id
属性,那么getElementById
方法将会返回null
。推荐阅读
- React报错之Cannot find name
- React报错之Object is possibly null
- React|React UI组件库——如何快速实现antd的按需引入和自定义主题
- React|【React路由】编程式路由导航和withRouter的使用——push / replace
- React|React路由组件传参的三种方式——params、search、state
- React|【React组件】github搜索案例之 父子组件通信 (附源码)
- React|【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- React|【ReactRouter5】路由的模糊匹配,重定向以及嵌套路由
- React|【React】深入理解React组件生命周期----图文详解(含代码)