The text starts here~
Overview
When we try to access the value
property on an element of type HTMLElement
, the error "Property 'value' does not exist on type 'HTMLElement'" is generated. To resolve the error, use a type assertion to assert the element type as HTMLInputElement
before accessing the property.
Here is an example to show how the error occurs.
// App.tsx
import {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>
);
}
The reason we get the error is because, the type returned by the document.getElementById method is HTMLElement | null
and the value property does not exist on the type HTMLElement
.
type assertion
To resolve the error, use a type assertion to assert the element type as HTMLInputElement
(or HTMLTextAreaElement
if you use the textarea
element type).
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>
);
}
You can also use a type assertion inline, just before accessing the value property.
// App.tsx
import {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>
);
}
Type assertions are used when we have type information for a value, but TypeScript has no way of knowing it.
We're effectively telling TypeScript that theinput
variable stores aHTMLInputElement
, don't worry about it.
If you were using a textarea
element, you would use the HTMLTextAreaElement
type instead.
union type
If you want more precise control over the type, you can use a union type to set the type to HTMLInputElement | null
.
// App.tsx
import {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
type is correct because the document.getElementById()
method returns a null
value if the element with the provided id does not exist in the DOM.
Note that we use the optional chaining ( ?.
) operator to short-circuit the operation if the reference is null ( null
or undefined
).
In other words, if the input
variable stored a null
value, we would not have attempted to access the property of null
and would have gotten a runtime error.
type guard
You can also use a simple if
statement as a type guard to ensure that the input
variable does not store a null
value.
// App.tsx
import {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
。
It is always a best practice to include null
in the type assertion, because if the provided element of ---670383ebc2670bab5354a93bf2b2189e id
is not found, the getElementById
method will return null
.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。