正文从这开始~
当我们试图访问一个类型为HTMLElement的元素上的value属性时,会产生"Property 'value' does not exist on type 'HTMLElement'"错误。为了解决该错误,在访问属性之前,使用类型断言将元素类型断言为HTMLInputElement。
这里有个示例用来展示错误是如何发生的。
// App.tsximport {useEffect} from 'react';export default function App() { useEffect(() => { const input = document.getElementById('message'); // ?? Property 'value' does not exist on type 'HTMLElement'.ts(2339) console.log(input?.value); }, []); return ( <div> <input id="message" defaultValue="Initial value" /> </div> );}我们得到错误的原因是因为,document.getElementById方法返回的类型为HTMLElement | null ,并且value属性不存在于HTMLElement类型上。
为了解决该错误,使用类型断言将元素类型断言为HTMLInputElement(或者HTMLTextAreaElement,如果你使用textarea元素键入)。
import {useEffect} from 'react';export default function App() { useEffect(() => { // ? type element as HTMLInputElement const input = document.getElementById('message') as HTMLInputElement; console.log(input?.value); // ??? "Initial value" }, []); return ( <div> <input id="message" defaultValue="Initial value" /> </div> );}你也可以在内联中使用一个类型断言,就在访问值属性之前。
// App.tsximport {useEffect} from 'react';export default function App() { useEffect(() => { // ??? inline type assertion const value = (document.getElementById('message') as HTMLInputElement).value; console.log(value); }, []); return ( <div> <input id="message" defaultValue="Initial value" /> </div> );}当我们拥有一个值的类型信息,但是TypeScript无从得知时,就会使用类型断言。
我们有效地告诉TypeScript,
input变量存储了一个HTMLInputElement,不用担心它。
如果你正在使用一个textarea元素,你将使用HTMLTextAreaElement类型来代替。
如果你想更精确地控制类型,你可以使用一个联合类型来设置类型为HTMLInputElement | null。
// App.tsximport {useEffect} from 'react';export default function App() { useEffect(() => { // ? type element as HTMLInputElement | null const input = document.getElementById('message') as HTMLInputElement | null; console.log(input?.value); // ??? "Initial value" }, []); return ( <div> <input id="message" defaultValue="Initial value" /> </div> );}HTMLInputElement | null类型是正确的,因为如果提供id的元素不存在于DOM中,document.getElementById()方法就会返回一个null值。
需要注意的是,我们使用了可选链(?.)操作符来短路运算,如果引用是空值的话(null或者undefined)。
换句话说,如果input变量存储了一个null值,我们就不会试图访问null的属性,而得到一个运行时错误。
你也可以使用一个简单的if语句作为类型守卫,以确保input变量不存储一个null值。
// App.tsximport {useEffect} from 'react';export default function App() { useEffect(() => { const input = document.getElementById('message') as HTMLInputElement | null; if (input != null) { console.log(input.value); // ??? "Initial value" } }, []); return ( <div> <input id="message" defaultValue="Initial value" /> </div> );}TypeScript知道
input变量在if块中的类型是HTMLInputElement,并允许我们直接访问其value属性。
在类型断言中包含null总是一种最佳实践,因为如果没有找到所提供的id的元素,getElementById方法将返回null。