正文从这开始~

总览

在React中,当我们试图访问类型为HTMLElement 的元素上不存在的属性时,就会发生Property 'X' does not exist on type 'HTMLElement'错误。为了解决该错误,在访问属性之前,使用类型断言来正确地类型声明元素。

这里有三个例子来展示错误是如何发生的。

// App.tsx

import {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 (
<div>
<input
id="first_name"
type="text"
name="first_name"
defaultValue="Initial Value"
/> <a id="link" href="<https://google.com>" target="_blank" rel="noreferrer">
Open Google
</a> <button id="btn">Submit</button>
</div>
);
}

产生错误的原因是,document.getElementById方法的返回类型是HTMLElement | null,但是我们试图访问的属性不存在于HTMLElement 类型。

类型断言

为了解决这个错误,使用类型断言来为元素正确地进行类型声明。比如说,类型断言为HTMLInputElementHTMLButtonElementHTMLAnchorElementHTMLImageElementHTMLDivElementHTMLTextAreaElement等等。这取决于你所处理的元素。

这些类型始终命名为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 (
<div>
<input
id="first_name"
type="text"
name="first_name"
defaultValue="Initial Value"
/> <a id="link" href="<https://google.com>" target="_blank" rel="noreferrer">
Open Google
</a> <button id="btn">Submit</button>
</div>
);
}

类型断言被用于我们知道值的类型信息,但是TypeScript却不知道的时候。

我们明确的告诉TypeScript,input变量上存储了HTMLInputElement ,并让TS不要担心。

同样的,我们将link变量类型声明为HTMLAnchorElement,将btn变量类型声明为HTMLButtonElement

你可以在访问一个属性之前,内联使用类型断言。

import {useEffect} from 'react';

export default function App() {
useEffect(() => {
const value = (document.getElementById('first_name') as HTMLInputElement).value;
console.log(value);
}, []); return (
<div>
<input
id="first_name"
type="text"
name="first_name"
defaultValue="Initial Value"
/> <a id="link" href="<https://google.com>" target="_blank" rel="noreferrer">
Open Google
</a> <button id="btn">Submit</button>
</div>
);
}

如果你只需要访问属性一次,并且不希望将元素分配给变量,那么内联类型声明可以完成这项工作。

如果你想更精确地处理元素的类型,可以使用联合类型将类型声明为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 (
<div>
<input
id="first_name"
type="text"
name="first_name"
defaultValue="Initial Value"
/> <a id="link" href="<https://google.com>" target="_blank" rel="noreferrer">
Open Google
</a> <button id="btn">Submit</button>
</div>
);
}

HTML***Element 或者null 类型是最准确的类型,因为如果DOM元素上不存在id属性,那么document.getElementById()将会返回null

你可以使用可选链操作符(?.)在访问属性之前来进行短路运算,如果引用是空值(null或者undefined)的话。

或者,你可以使用简单的if语句作为类型守卫,就像我们对button处理的那样。

总结

最佳实践是在类型断言中包含null 。因为如果元素上面不提供id属性,那么getElementById方法将会返回null

React报错之Property 'X' does not exist on type 'HTMLElement'的更多相关文章

  1. React报错之Property 'value' does not exist on type 'HTMLElement'

    正文从这开始~ 总览 当我们试图访问一个类型为HTMLElement的元素上的value属性时,会产生"Property 'value' does not exist on type 'HT ...

  2. React报错之Property 'value' does not exist on type EventTarget

    正文从这开始~ 总览 当event参数的类型不正确时,会产生"Property 'value' does not exist on type EventTarget"错误.为了解决 ...

  3. React报错之Parameter 'props' implicitly has an 'any' type

    正文从这开始~ 总览 当我们没有为函数组件或者类组件的props声明类型,或忘记为React安装类型声明文件时,会产生"Parameter 'props' implicitly has an ...

  4. React报错之Parameter 'event' implicitly has an 'any' type

    正文从这开始~ 总览 当我们不在事件处理函数中为事件声明类型时,会产生"Parameter 'event' implicitly has an 'any' type"错误.为了解决 ...

  5. 解决TS报错Property 'style' does not exist on type 'Element'

    在使用queryselector获取一个dom元素,编译时却报错说property 'style' does not exist on type 'element'. 原因:这是typescript的 ...

  6. react 报错的堆栈处理

    react报错 Warning: You cannot PUSH the same path using hash history 在Link上使用replace 原文地址https://reactt ...

  7. elasticsearch查询:启动项目报错No property ... found for...Did you mean '...'?

    网上找的案例是: 实体类字段定义:private String sku_no;dao中接口名定义:Goods findBySkuNo(String skuNo);spring-data按照接口方法定义 ...

  8. react中使用typescript时,error: Property 'setState' does not exist on type 'Home'

    问题描述: 我在react中用typescript时,定义一个Home组件,然后在组件里用setState时会有这样一个报错:(如图)Property 'setState' does not exis ...

  9. notification 报错the method build() is undefined for the type Notificatin.Builder

    notification 报错the method build() is undefined for the type Notificatin.Builder 这事api版本号太低导致的 Notifi ...

随机推荐

  1. 一次 HTTP 请求就需要一次 TCP 连接吗?

    一次 HTTP 请求就需要一次 TCP 连接吗? 本文写于 2021 年 2 月 9 日 太长不看版本:短连接需要,长连接不需要. 一次 HTTP 请求就需要一次 TCP 连接吗? TCP 的连接与断 ...

  2. 归约与分组 - 读《Java 8实战》

    区分Collection,Collector和collect 代码中用到的类与方法用红框标出,可从git库中查看 收集器用作高级归约 // 按货币对交易进行分组 Map<Currency, Li ...

  3. vue3常见问题及解决方案(四)父组件切换行,然后子组件切换tab,子组件内的数据不刷新

    问题描述 父组件切换行,然后子组件切换tab,子组件内的数据不刷新. 例如父组件为订单,子组件为订单相关商品和相关客户,商品和客户使用tab选项卡组织. 当tab显示商品页时,切换订单,商品页内容跟着 ...

  4. 附001.Python多版本环境管理

    一 环境背景 由于Python的版本过多,且不同版本之间差异性较大.同时又因系统底层需要调用当前版本Python,所以不能随意变更当前系统Python版本.因此,在多版本共存的情况下,Python多环 ...

  5. vue大型电商项目尚品汇(前台篇)day05终结篇

    前台部分到此结束,一路走来还挺怀念,今天主要是对整个项目的完成做一个最后的收尾工作,对于功能上的需求没有什么了,主要就是项目上线的一些注意事项. 一.个人中心二级路由 当我们点击查看订单应该跳转到个人 ...

  6. markdowm使用学习

    markdowm学习 标题(#/##/###/####) 三级标题 四级标题 字体(*/) hello world! hello world! hello world! hello world! he ...

  7. 【生成对抗网络学习 其一】经典GAN与其存在的问题和相关改进

    参考资料: 1.https://github.com/dragen1860/TensorFlow-2.x-Tutorials 2.<Generative Adversarial Net> ...

  8. 5-5配置Mysql复制 基于日志点的复制

    配置MySQL复制 基于日志点的复制配置步骤 设置简单密码(可以选择不需要) set GLOBAL validate_password_length=6; set global validate_pa ...

  9. 攻防世界pwn题:实时数据检测

    0x00:查看文件 一个32位的文件,canary.NX.PIE保护机制均关闭. 0x01:用IDA进行静态分析 程序很简单,输入一串字符(个数限制:512),然后再输出.最后根据key变量进行条件语 ...

  10. DotNET程序员面向API编程的正确姿势

    原文:https://blog.csdn.net/u013201439/article/details/49981071 补充:按照步骤成功加载文档后,选择索引可以快速发现相关的内容,如图