【问题标题】:Typescript and custom elements properties compilation issue打字稿和自定义元素属性编译问题
【发布时间】:2019-03-12 04:22:03
【问题描述】:

我有这个自定义元素:

class CustomElement extends HTMLElement{
 constructor(){ super(); }
config: ConfigModel;
}
window.customElements.define('my-element', CustomElement);

然后,在代码的某个地方,我有这样的东西:

const myElement = document.createElement('my-element');
myElement.config = config;

TS 在此处抛出错误: error TS2339: Property 'config' does not exist on type 'HTMLElement'.

知道如何解决这个问题吗?

编辑: 建议转换元素的类型。虽然这可行,但它确实带来了 2 个问题:

  1. 我不一定希望每个服务都使用自定义元素 了解自定义元素的类
  2. 如果我模拟自定义 测试元素,服务中硬编码的自定义元素 不允许嘲笑。

这是解释它的要点:https://gist.github.com/YonatanKra/de42be2fa5499157169ef141ba377998

【问题讨论】:

    标签: javascript typescript custom-element


    【解决方案1】:

    您需要将元素转换为预期的类型,因为 Typescript 在这种情况下无法知道类型。

    const myElement = <CustomElement>document.createElement('my-element');
    

    您还需要在 CustomElement 中继承 HTMLElement 类:

    class CustomElement extends HTMLElement {
    

    根据进一步的问题编辑答案:

    显然,如果您想访问 CustomElement 对象的属性,您需要键入 cast。但是在所有其他情况下,您可以只使用默认的HTMLElement 类型。它仍然应该允许您对对象执行某些操作,而不是与 CustomElement 相关的任何操作。所以不是每个服务都需要知道它是一个CustomElement 对象。

    对于模拟,您可以创建一个继承自 CustomElementCustomElementMock

    class CustomElementMock extends CustomElement {
    }
    

    模拟版本仍然是CustomElement 类型,您的原始代码仍应接受它。但是,在模拟类中,您可以覆盖所有功能以不执行任何操作或返回模拟数据。

    【讨论】:

    • 嗨,谢谢。我忘记在我的问题中添加extends。编辑添加它。铸造技巧有效 - 但只是成功的一半。假设我也在测试一个使用该元素的服务,但想模拟它 - 所以在服务中我将使用“真实”的,但在测试中我将使用“模拟”。这是一个要点:gist.github.com/YonatanKra/de42be2fa5499157169ef141ba377998
    • 已编辑以包含您的其他问题。让我知道这是否有帮助。
    • 感谢您的详细回复。当我使用@angular/elements 尝试此操作时,我仍然遇到问题。我当然可以创建导出createCustomElement 的结果的整个样板,但我希望在应用程序开始时避免这种情况(尤其是在使用 TDD 并且只想测试一个简单的属性分配时......)。
    • 查看Angular documentation 关于自定义元素,他们以不同的方式定义其元素。 Angular 文档给出的示例是否有特定原因无法调整以满足您的需求?
    • 希望避免更多代码,但如果您想使用 TS,我想您必须这样做 :) 非常感谢!
    【解决方案2】:

    使用document.createElement('my-element') as CustomElement

    【讨论】:

    • 正如我评论的那样,这不好,因为我不希望每个使用自定义元素的服务都知道它的类...
    • 如果每个使用自定义元素的服务都不知道它的类,那么每个服务也不会知道你拥有的自定义属性,即config,因此你必须指定是在某处,查看您的代码示例,最好的方法是在服务中指定方法的返回类型并执行上述转换。
    • 这是角度元素的更大问题。在 Angular 元素中,“类”是由 @angular/elements 转换为 HTMLElement 的组件。所以我不能只导入组件,我需要导入角度元素转换的结果。它需要编写大量代码才能满足打字稿。我希望它值得(或者有更好的方法)。
    • 嗯..我不知道。您能准确告诉我测试中的错误/异常/失败消息是什么吗?
    • 使用角度元素,你必须以这种方式投射,as NgElement &amp; WithProperties&lt;{content: string}&gt;; angular.io/guide/elements 我觉得你的问题正在发散和演变很多,这就是我下车的地方。
    猜你喜欢
    • 2015-12-17
    • 1970-01-01
    • 2017-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-15
    • 2011-03-13
    相关资源
    最近更新 更多