Lit element typescript 项目全局接口声明有必要吗?

Ole*_*Ole 4 javascript web-component typescript lit-element

Typescript Lit Element 入门项目在示例元素的底部包含此全局接口声明:

declare global {
  interface HTMLElementTagNameMap {
    'my-element': MyElement;
  }
}
Run Code Online (Sandbox Code Playgroud)

有必要吗?它是干什么用的?

djl*_*auk 7

有必要吗?

不,此声明对于基于 LitElement 的自定义元素的工作来说不是必需的。

它是干什么用的?

这是 TypeScript 的一项功能,并非 LitElement 特有的。

此声明有助于 TypeScript 在与 DOM API 交互时提供强类型。JavaScript DOM API 当然不知道也不关心类型,但 TypeScript 知道。通过这种机制,您可以将自定义元素的类型添加到 DOM API。

一个例子可能会更好地说明这一点。假设这个非常简单的自定义元素:

class HelloWorldElement extends HTMLElement {

  name = 'world'; // public 'name' member with default value

  // ... element internals left aside,
  // just assume this.name is used somewhere ...
}

window.customElements.define('hello-world', HelloWorldElement);
Run Code Online (Sandbox Code Playgroud)

现在考虑将此元素与 DOM API 一起使用:

const el = document.createElement('hello-world');

// el has the very generic type HTMLElement
el.name = 'custom elements';  // error! HTMLElement has no member 'name'
Run Code Online (Sandbox Code Playgroud)

TypeScript 不会让你这么做。当语句在运行时执行时,它(尚)无法知道标签名称是否与实例hello-world一起出现,但在编译时会检查类型安全性。HelloWorldElementcustomElements.define(...)

但是如果你扩展 的声明HTMLElementTagNameMap,TypeScript 将知道元素的类型<hello-world></hello-world>

// with the added declaration
declare global {
  interface HTMLElementTagNameMap {
    'hello-world': HelloWorldElement;
  }
}

const el = document.createElement('hello-world');
// el has type HelloWorldElement
el.name = 'custom elements';  // OK. HelloWorldElement has a string member 'name'
Run Code Online (Sandbox Code Playgroud)

如果您想了解更多详细信息,可以在TypeScript 手册中找到它们。