解决React报错Property 'X' does not exist on type 'HTMLElement'
Borislav Hadzhiev 人气:0总览
在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>" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" target="_blank" rel="noreferrer"> Open Google </a> <button id="btn">Submit</button> </div> ); }
产生错误的原因是,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 ( <div> <input id="first_name" type="text" name="first_name" defaultValue="Initial Value" /> <a id="link" href="<https://google.com>" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" 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>" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" 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>" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" 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
。
加载全部内容