【问题标题】:What is the type of the <svg> element in typescript [duplicate]打字稿中 <svg> 元素的类型是什么[重复]
【发布时间】:2020-11-19 18:27:57
【问题描述】:

我正在实现以下类:

export class BbSVGElement extends HTMLElement implements HTMLCanvasElement { ... }

问题是我在打字稿中找不到&lt;svg&gt;元素的类型:&lt;span&gt;元素是HTMLSpanElement&lt;canvas&gt;元素是HTMLCanvasElement等。

我问是因为要实现一个简单的任务,例如height() 函数,我需要获取元素的边界框。根据this stack overflow answer,这是正确的做法:

height(): number { return this.getBBox().height}

但是既然this指的是HTMLElement,当然Property 'getBBox' does not exist on type 'BbSVGElement'.ts(2339)

所以我尝试了各种类型的铸件;比如:

return (<SVGElement> this).getBBox().width
return (<SVGSVGElement> this).getBBox().width

我当然可以做类似的事情

return (<any> this).getBBox().width

return this.offsetWidth // <-- This property here comes from HTMLElement

但如果可能的话,我宁愿不要。

那么:什么是正确的演员阵容?还是我错过了其他选择?

【问题讨论】:

  • 这里记录了 SVG 的 SVG-DOM 接口类型:developer.mozilla.org/en-US/docs/Web/API/…
  • SVGElement 不会在 HTML 下......它是独立的。我不使用 Typescript,但我猜您必须导入其他内容。
  • 您在寻找SVGGraphicsElement吗?这就是getBBox() method 的类型,对吧?
  • BbSVGElement 代表什么?您不应该使用extends HTMLElement implements HTMLCanvasElement,因为您没有重新实现&lt;canvas&gt;(而且&lt;canvas&gt; 和SVG 无论如何都是完全不同的东西)——并且您不应该扩展HTMLElement,除非您正在定义HTML5 Web 组件。你到底想完成什么?
  • @MarcheRemi 名称 SVGOrHtmlElement 不正确,因为它是交集类型,而不是联合类型。您的案例的正确名称是 SVGAndHtmlElement(或我在发布的答案中使用的 SvgInHtml 名称)。

标签: html typescript casting


【解决方案1】:

TypeScript 中&lt;svg&gt; 元素的类型是什么?

*.svg 文档(即 SVG DOM)中&lt;svg&gt; 元素的接口类型为SVGElement。 HTML 文档(即 HTML DOM)中的&lt;svg&gt; 元素的类型实际上是一个无原型对象实现了 HTMLElement SVGElement

所以在 TypeScript 中,您可以通过使用 intersection type 来表示 DOM 中的 &lt;svg&gt; 元素(它表示结合了两个或多个 所有成员 的类型类型,与 联合类型 相比,联合类型表示结合了两种或多种类型的共享成员的类型)。

像这样:

type SvgInHtml = HTMLElement & SVGElement;

const svgElement: SvgInHtml = document.createElement('svg') as SvgInHtml;

const svgHeight = svgElement.getBBox().height; // Using `SVGElement.getBBox()`.
const htmlWidth = svgElement.offsetWidth;      // Using `HTMLElement.offsetWidth`

我看到您想使用 派生 类来表示这一点 - 但这是不正确的(因为类继承只允许单个父类),而是使用非封装的 type SvgInHtml 引用,或将其封装在一个对象或新类中(没有超类):

type SvgInHtml = HTMLElement & SVGElement;

class MySvgWrapper {

    constructor( private readonly svgElement: SvgInHtml ) {
    }

    get height(): number {
        return this.svgElement.getBBox().height;
    }
}

(这是我在正确理解您的问题之前发布的原始答案 - 我将其保留在这里并可以访问,因为我觉得它可能对其他发现此问题但与您的问题不同的人仍然有用):

所有(大多数?)SVG元素的基本SVG-DOM接口是SVGElementwhich is documented on MDN

假设您使用的是 TypeScript 3.x 或更高版本,它在 lib.dom.d.ts 中具有 SVG-DOM 接口(请参阅我在行下方的回答内容),那么您需要将您的 class 声明更改为:

export class MySVGElement extends SVGElement {
    
}

从 TypeScript 3.x 开始,TypeScript 的 HTML DOM 类型“标准库”包括 lib/lib.dom.d.ts 中的 SVG DOM 接口,因此您无需下载、导入或添加任何内容 - 只需使用 SVGElement (及其派生接口)。

If you open the current TypeScript lib.dom.d.ts in GitHub 您可以搜索"SVGElement"(以及任何其他 SVG-DOM 接口,例如 SVGGraphicsElement)并查看它的声明:

例如:

/** SVG elements whose primary purpose is to directly render graphics into a group. */
interface SVGGraphicsElement extends SVGElement, SVGTests {
    readonly transform: SVGAnimatedTransformList;
    getBBox(options?: SVGBoundingBoxOptions): DOMRect;
    getCTM(): DOMMatrix | null;
    getScreenCTM(): DOMMatrix | null;
    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGGraphicsElement, ev: SVGElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
    addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
    removeEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGGraphicsElement, ev: SVGElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
    removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
}

如果您遇到任何与未知/未定义类型相关的错误,请将其发布为新的 StackOverflow 问题。

【讨论】:

  • 感谢您的回复!虽然对我有用的是HTMLElement &amp; SVGSVGElement!像这样:const [ref, { width }] = useMeasure&lt;HTMLElement &amp; SVGSVGElement&gt;();
猜你喜欢
  • 2016-07-29
  • 2016-11-06
  • 1970-01-01
  • 2022-01-19
  • 2019-01-26
  • 1970-01-01
  • 2017-03-11
  • 2021-03-14
  • 2019-01-10
相关资源
最近更新 更多