简体   繁体   English

TS2339:“元素”类型上不存在属性“样式”

[英]TS2339: Property 'style' does not exist on type 'Element'

Here's the code:这是代码:

const test = Array.from(document.getElementsByClassName('mat-form-field-infix'));
test.forEach((element) => {
    element.outerHTML = '<div class="good-day-today" style="width: 0px;"></div>'; // Please note that this line works fine!
    element.style.padding = '10px';
    element.style.borderTop = '0';
});

Error I get when compiled:编译时出现的错误:

ERROR in src/app/ / .component.ts(101,21): error TS2339: Property 'style' does not exist on type 'Element'. src/app/ / .component.ts(101,21) 中的错误:错误 TS2339:“元素”类型上不存在属性“样式”。 src/app/ / .component.ts(102,21): error TS2339: Property 'style' does not exist on type 'Element'. src/app/ / .component.ts(102,21):错误 TS2339:“元素”类型上不存在属性“样式”。

How can I fix it?我该如何解决?

I tried to remove the Array.from... part, tried to use for of and for in , tried as any , but above is the way I have to do it.我试图删除Array.from...部分,尝试使用for offor in ,尝试as any ,但以上是我必须这样做的方式。

You need a typecast:你需要一个类型转换:

Array.from(document.getElementsByClassName('mat-form-field-infix') as HTMLCollectionOf<HTMLElement>)

That's because getElementsByClassName only returns HTMLCollection<Element> , and Element does not have a style property.这是因为getElementsByClassName 只返回HTMLCollection<Element> ,而Element没有style属性。 The HTMLElement however does implement it via it's ElementCSSInlineStyle extended interface.然而, HTMLElement 确实通过它的ElementCSSInlineStyle扩展接口实现了它。

Note that this typecast is typesafe in the way that every Element is either a HTMLElement or an SVGElement , and I hope that your SVG Elements don't have a class.请注意,这种类型转换是类型安全的,因为每个Element都是HTMLElementSVGElement ,我希望您的SVG 元素没有 class。

Another option is to use querySelectorAll and a type parameter.另一种选择是使用querySelectorAll和类型参数。 getElementsByClassName is not generic, but querySelectorAll is - you can just pass the type of the elements that will be selected, like this: getElementsByClassName不是通用的,但querySelectorAll是 - 您可以只传递将被选择的元素的类型,如下所示:

const test = document.querySelectorAll<HTMLElement>('.mat-form-field-infix');

This doesn't require any type casting, and it will allow you to use forEach immediately, rather than converting it to an array first.这不需要任何类型转换它将允许您立即使用forEach ,而不是先将其转换为数组。 ( getElementsByClassName returns an HTMLCollection, which does not have a forEach method; querySelectorAll returns a NodeList , which does have a forEach method, at least on somewhat up-to-date browsers. To support ancient browsers too, you'll need a polyfill , or convert it to an array first.) getElementsByClassName返回一个 HTMLCollection,它没有forEach方法; querySelectorAll返回一个NodeList ,它确实有一个forEach方法,至少在一些最新的浏览器上是这样。为了也支持古老的浏览器,你需要一个polyfill ,或先将其转换为数组。)

If you happen to just need a single element, you can use querySelector , which is generic as well:如果您碰巧只需要一个元素,则可以使用querySelector ,它也是通用的:

const elm = document.querySelector<HTMLElement>('.foo')!;
elm.style.padding = '10px';

Another benefit of querySelectorAll (and querySelector ) over the many other options is that they accept CSS selector strings, which can be far more flexible and precise. querySelectorAll (和querySelector )相对于许多其他选项的另一个好处是它们接受 CSS 选择器字符串,这可以更加灵活和精确。 For example, the selector string例如,选择器字符串

.container > input:checked

will select children of <div class="container"> which are <input> s and are checked.将 select 的<div class="container">的孩子是<input> s 并被检查。

I was also facing a similar type of issue while doing我在做的时候也面临着类似的问题

document.querySelectorAll(".<className>"); 

so instead of adding the style property, I simply got around it by just adding another class.所以我没有添加样式属性,而是通过添加另一个 class 来解决它。

example:例子:

//css file
    .<classname> {
        display: none;
      }
    .<classname>.show {
        display: flex;
      }

//ts file
elements.forEach((ele, index) => {
const errors = something.length;
if (index < errors) {
  ele.classList.add("show");
} else {
  ele.classList.remove("show");
}

}); }); }; };

A workaround could be doing something like this:一种解决方法可能是这样做:

element["style"].padding = '10px';
element["style"].borderTop = '0';

Maybe it's not the best solution, but it should work, I used it multiple times:)也许这不是最好的解决方案,但它应该可以工作,我多次使用它:)

When you set the outerHTML, you're destroying the original element that was there.当您设置 outerHTML 时,您正在破坏那里的原始元素。 So, your styling doesn't work.所以,你的造型不起作用。

You'll notice that if you change it to set innerHTML, your styling does work.您会注意到,如果您将其更改为设置 innerHTML,您的样式确实有效。

This does not do the same exact thing, but I hope it points you in the right direction.这不会做同样的事情,但我希望它能为您指明正确的方向。

const test = Array.from(document.getElementsByClassName('mat-form-field-infix'));
test.forEach((element) => {
    element.innerHTML = '<div class="good-day-today" style="width: 0px;"></div>'; // Please note that this line works fine!
    element.style.padding = '10px';
    element.style.borderTop = '0';
});

I think I found a way easier method:我想我找到了一种更简单的方法:

Just create an index.d.ts file and add:只需创建一个 index.d.ts 文件并添加:

interface Element {
    style: CSSStyleDeclaration
}

Maybe this could help:也许这会有所帮助:

let element = <HTMLElement> document.getElementsByClassName(className)[0];

The answer from Jonas Wilms is not totally right (anymore?). Jonas Wilms 的回答并不完全正确(现在?)。

While I suspect that type casting will not cause any problems in this case, I would still avoid type casting whenever possible.虽然我怀疑在这种情况下类型转换不会导致任何问题,但我仍然会尽可能避免类型转换。 In this case, you can avoid type casting with instanceof narrowing :在这种情况下,您可以避免使用instanceof narrowing进行类型转换:

const test = Array.from(
  document.getElementsByClassName('mat-form-field-infix')
)
test.forEach((element) => {
  if (!(element instanceof HTMLElement)) {
    return
  }

  element.outerHTML =
    '<div class="good-day-today" style="width: 0px;"></div>' // Please note that this line works fine!
  element.style.padding = '10px'
  element.style.borderTop = '0'
})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM