【问题标题】:Typescript "Property does not exists on type Element"打字稿“元素类型上不存在属性”
【发布时间】:2017-08-07 19:56:00
【问题描述】:

我正在使用 Typescript 开始我的旅程。所以我在我的 Html 和 .ts 文件中有 video 标签这些行:

...
class KomakhaPlayer {
  private container = ...;
  private video: Element = this.container.getElementsByClassName( 'video' )[ 0 ];
  private controls = ...;

  constructor(){
    this.video.controls = false; // ts error
    ...
  }
}
...

如您所见,this.video 具有 Element 类型,但在 this.video.controls 下面会抛出 Typescript 错误 “Element”类型上不存在属性“控件” .

暂时我将Element 类型更改为any,但我想知道如何正确解决此错误并在以后处理类似问题。提前致谢!

解决方案: 所以正确的方法是这样定义的:

private video: HTMLVideoElement = <HTMLVideoElement>this.container.getElementsByClassName( 'video' )[ 0 ];

@deceze 在 cmets 下面的解释

【问题讨论】:

  • 使用this. controls 不是吗?而不是this.video.controls
  • Element 是自定义类还是您正在使用的库的一部分
  • @Smit, no this.video.controls, controls 是 video 标签的属性
  • private video: Element = this.container.getElementsByClassName( 'video' )[ 0 ]; 避免分配外部方法。而是将其放在构造函数中。
  • Element 确实没有属性controlsHTMLVideoElement 可能。

标签: javascript typescript types


【解决方案1】:

Element 是一个非常通用的根对象,它确实没有controls 属性。见https://developer.mozilla.org/en-US/docs/Web/API/Element。您正在寻找的是一个HTMLVideoElement,它继承自HTMLMediaElement,后者具有controls 属性。

Typescript 完全正确:你告诉它你正在使用 Element,Typescript 警告你 Element 不知道有 controls

【讨论】:

  • 谢谢,我的工作方式如下:private video: HTMLVideoElement = &lt;HTMLVideoElement&gt;this.container.getElementsByClassName( 'video' )[ 0 ];。但有一件事我不明白为什么我需要投&lt;HTMLVideoElement&gt;? Typescript 无法判断这是视频类型吗?
  • 不,它不能。 getElementsByClassName('video') 究竟会返回什么元素只在运行时知道,而不是在编译时知道。在编译时,最好的 Typescript 可以推断出它将是某种Element
【解决方案2】:

鉴于你的陈述(强调我的)

所以我在我的 Html 和 .ts 文件中有 video 标签 这些行:

class KomakhaPlayer {
  private video: Element = this.container.getElementsByClassName('video')[0];    
  constructor(){
    this.video.controls = false; // ts error
  }
}

您犯了两个严重错误。

首先,要获得正确的运行时行为,您需要通过元素的标签名称。那就是你使用document.getElementsByTagName 而不是document.getElementsByClassName

解决这个问题

class KomakhaPlayer {
  private video: Element = this.container.getElementsByTagName('video')[0];    
  constructor(){
    this.video.controls = false; // ts error
  }
}

仍然有一个错误。

这是因为一个严重的误解。您在程序中过度指定了类型,从而阻止了该语言执行其高度复杂的类型推断。如果您从video 字段中删除: Element 类型注释,您的代码可以进行类型检查,因为编译器有更多 类型信息 更少。少说多得。

class KomakhaPlayer {
  private video = this.container.getElementsByTagName('video')[0];    
  constructor(){
    this.video.controls = false;
  }
}

Playground Link

TypeScript 是关于拥有类型信息而不是类型写入类型注释。 在编译器不知道类型是什么或何时要形式化 API 时编写类型注释,而不是在初始化字段时编写。

【讨论】:

    【解决方案3】:

    这在我的代码中对我有用。

    const value = 'hello world';
    
    const el: HTMLElement = document.getElementById('id_of_element') as HTMLElement;
    el.innerHTML = value;
    

    【讨论】:

    • 这与问题无关,它是非常糟糕的代码。由于不安全的类型断言,您有一个误导性的注释和完全冗余的注释,仅 TS 允许。 document.getElementById('id_of_element') 返回HTMLElement | null。您不需要注释或 as HTMLElement 断言。 document.getElementById('id_of_element')?.innerHTML = value document.getElementById('id_of_element')!.innerHTML = value; 取决于您是否希望您的应用在存在具有该 ID 的元素时崩溃。
    猜你喜欢
    • 2016-08-15
    • 2017-03-02
    • 2021-09-07
    • 2019-02-06
    • 2017-03-26
    • 2017-09-06
    • 2020-05-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多