Typescript 认为 `this` 是抽象的,因为基类是抽象的,需要讨厌的强制转换

问题描述 投票:0回答:2

我有一个基类

abstract
,扩展
HTMLElement
,它调用
CustomElementRegistry.define
。 Typescript 不喜欢使用
this
作为第二个参数,因为基类是
abstract
。但这似乎是不正确的,因为显然最终类永远不可能是抽象的。我必须使用下面丑陋的演员阵容。有更好的方法吗?

abstract class CustomElement extends HTMLElement {
  constructor() {
    super();
  }
  // Without a cast, the `this` argument gets this error:
  // tsbug.ts:12:6 - error TS2345: Argument of type 'this' is not assignable to parameter of type 'CustomElementConstructor'.
  //   Type 'CustomElement' is not assignable to type 'CustomElementConstructor'.
  //     Type 'CustomElement' provides no match for the signature 'new (...params: any[]): HTMLElement'.
  register() {
    customElements.define(
     "custom-element",
     this, // This argument gets the error.
     // If you replace the above `this` argument with the one below, it works.
     // this as unknown as new () => HTMLElement,
     {});
  }
}

class MyElement extends CustomElement {
  constructor() {
    super();
    this.register();
  }
}

const e = new MyElement();
typescript abstract-class
2个回答
1
投票

您尝试做的事情是不正确的。

CustomElement
的实例不应该尝试使用自定义元素注册本身。该逻辑比类内部的逻辑更高。

考虑一下如果你写的话会发生什么

const a = new MyElement();
const b = new MyElement();

这两个都会尝试注册,并使用自定义元素注册表重新注册自己。此外,每次您尝试在标记中使用自定义元素时都会发生这种情况。这不好。

相反,您的代码应该对更接近的设置进行建模:

customElements.define("custom-element", MyElement, {});
const a = new MyElement();
const b = new MyElement();

抛开设计问题不谈,您正在寻找的东西在正确的 OO 范式中是不可能实现的。

类不会获得可动态访问的对其自身的静态引用。 TypeScript 正确标记了一个问题:

customElements.define(
     "custom-element",
     this, 
// This is a reference to an *instance* of a class, not to a constructor. 
/// Casting will not make it work. You need a reference to the class you want to register.
     {});

-2
投票

customElements.define
的第二个参数必须是
CustomElementConstructor
的实例,它在“lib.dom.d.ts”中定义如下:

interface CustomElementConstructor {
    new(...params: any[]): HTMLElement;
}

因此,您的代码错误,因为您传递的是 HTMLElement(子类)的 instance,而不是传递 constructor 作为第二个参数。

也就是说,这只是不是定义自定义 HTML 元素的正确方法。如果您询问(在评论中),我可以对此进行扩展,无论如何,作为初学者,这里是相关文档的链接:https://developer.mozilla.org/en-US/docs/Web/API/ Web_Components/使用_custom_elements

[注意:我已经删除了我最初发布的代码,因为它不安全,不仅不清楚而且实际上没有用:例如我在尝试它的变体时成功地使 TS 游乐场崩溃了。]

© www.soinside.com 2019 - 2024. All rights reserved.