5

React报错之Property 'value' does not exist on type 'HTMLElement' - chuckQu

 1 year ago
source link: https://www.cnblogs.com/chuckQu/p/16629318.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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

正文从这开始~

当我们试图访问一个类型为HTMLElement的元素上的value属性时,会产生"Property 'value' does not exist on type 'HTMLElement'"错误。为了解决该错误,在访问属性之前,使用类型断言将元素类型断言为HTMLInputElement

property-value-does-not-exist-on-type-htmlelement.png

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

// 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>
  );
}

我们得到错误的原因是因为,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.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>
  );
}

当我们拥有一个值的类型信息,但是TypeScript无从得知时,就会使用类型断言。

我们有效地告诉TypeScript,input变量存储了一个HTMLInputElement,不用担心它。

如果你正在使用一个textarea元素,你将使用HTMLTextAreaElement类型来代替。

如果你想更精确地控制类型,你可以使用一个联合类型来设置类型为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类型是正确的,因为如果提供id的元素不存在于DOM中,document.getElementById()方法就会返回一个null值。

需要注意的是,我们使用了可选链(?.)操作符来短路运算,如果引用是空值的话(null或者undefined)。

换句话说,如果input变量存储了一个null值,我们就不会试图访问null的属性,而得到一个运行时错误。

你也可以使用一个简单的if语句作为类型守卫,以确保input变量不存储一个null值。

// 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属性。

在类型断言中包含null总是一种最佳实践,因为如果没有找到所提供的id的元素,getElementById方法将返回null


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK