0

HTMLElement inherits properties/methods from the Element interface. But, why on an instance of Element, it works even when I use the same properties and methods which are defined on HTMLElement. For example, in the given code, querySelector gives back Element which doesn't have a style property defined on it (HTMLElement does). But, it works when I apply the style property on it. Also, instanceof HTMLElement gives back true. It should only be instanceof Event, Node, and Element that gives back true since Element inherits from all three. I know HTMLElement can inherit methods/properties from Element but is it also vice-versa? MDN Docs DOM Interfaces

var somefield = document.querySelector('#lname');
somefield.style.background = 'yellow'
somefield instanceof HTMLElement; //True
  • Please show the element you are querying. – connexo Aug 09 '22 at 22:26
  • According to MDN, element is the base class that includes methods and properties for all kinds of elements. So HTMLElement inherits from element. https://developer.mozilla.org/en-US/docs/Web/API/Element – imvain2 Aug 09 '22 at 22:28
  • "The Document method querySelector() returns the first Element" does not mean it is *just* an Element. Any HTMLElement is both. –  Aug 09 '22 at 22:52

2 Answers2

1

querySelector will

return the first Element within the document that matches the specified selector, or group of selectors

An element can also be an HTMLElement. If element in the document happens to be an HTMLElement, then you will be able to use methods on HTMLElements on the result.

But the element isn't necessarily an HTMLElement. For example, if you happen to be working with an XML document, you won't get an HTMLElement in return, and won't be able to use HTMLElement methods:

const xmlStr = '<q id="a"><span id="b">hey!</span></q>';
const doc = new DOMParser().parseFromString(xmlStr, "application/xml");
const b = doc.documentElement.querySelector('#b');
console.log(b instanceof Element); // true
console.log(b instanceof HTMLElement); // false

// error:
b.style.background = 'yellow';

querySelector, if it finds anything at all, is guaranteed to return at least an Element, but it will often return a more specific type - not only an HTMLElement, but often something even more specific, like an HTMLInputElement - on which HTMLInputElement-specific methods and properties can be used.

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • "*`querySelector` is guaranteed to return at least an Element,*" - I may have missed your intent here, but (from MDN docs): "[it] returns the first Element within the document that matches the specified selector, or group of selectors. If no matches are found, `null` is returned" – David Thomas Aug 09 '22 at 22:39
  • Thanks for your help, I have one more confusion. When we use querySelector in ts, I can't use style or any of the other HTMLElement properties/methods on the Element. I need to first typecast it to HTMLElement to use properties defined in HTMLElement. So, is there some sort of type coercion that happens in js that automatically cast Element to HTMLElement or more specific like HTMLHeadingElement? Would appreciate if you have a link to something more exhaustive on it. – Muhammad Hamid Rafique Aug 10 '22 at 07:19
  • @MuhammadHamidRafique Yes, that's a TypeScript limitation that's annoyed me as well. Given the global identifier `document`, TypeScript alone can't distinguish whether it's an XML document or an HTML document (even though it's an HTML document 99% of the time) - and so calling `querySelector` on it will give you a generic Element, because TS can't narrow it down. You'll have to use generics to indicate the type you're selecting. `document.querySelector('.my-element')!.style.display = 'none';` – CertainPerformance Aug 10 '22 at 13:49
0

There are no elements on a page that are just Element instances. The interface serves as a parent "class" so HTMLElement, SVGElement and XULElement (and others) can inherit methods common to all elements.

connexo
  • 53,704
  • 14
  • 91
  • 128