@michaelallenwarner/el-is
v1.1.0
Published
A tiny TypeScript type guard (predicate-function) for narrowing a DOM element by tag-name.
Downloads
2
Maintainers
Readme
el-is
Install
npm install @michaelallenwarner/el-isRequirements
- TypeScript >= 5.0 (assuming you're using TypeScript)
Usage
import { elIs } from '@michaelallenwarner/el-is';
const htmlElement = document.querySelector('section'); // `HTMLElement | null`
if (elIs(htmlElement, 'SECTION')) {
// `htmlElement` now has type `HTMLElement & { tagName: 'SECTION' }`
}
const mathMlElement = document.querySelector('mrow'); // `MathMLElement | null`
if (elIs(mathMlElement, 'mrow')) {
// `mathMlElement` now has type `MathMLElement & { tagName: 'mrow' }`
}
const element = document.querySelector('.svg-path-element'); // `Element | null`
if (elIs(element, 'path')) {
// `element` now has type `Element & { tagName: 'path' }`
/*
But probably just do `if (element instanceof SVGPathElement)` instead!
Also, although `Element` will work as a type for the first parameter,
it's advisable to narrow it first to `HTMLElement`, `MathMLElement`, or `SVGElement`.
See Usage Notes below.
*/
}Usage Notes
The elIs() function takes two arguments—a maybe-null DOM element (el) and a string literal (tagName)—and returns the boolean result of a simple el?.tagName === tagName check, but with some TypeScript niceties described below.
But first, a quick warning: you probably should only use this function if the kind of element you're checking against doesn't have its own dedicated interface! For example, if you want to check whether el is a link, I can't think of any reason not to just do if (el instanceof HTMLAnchorElement), so that the type-narrowing gives you all the properties and methods that come with the more specific interface (like HTMLAnchorElement.href). The elIs() function is really for testing whether an element is of a kind that doesn't have its own interface, like <section>.
With that out of the way, here are the TypeScript niceties you get with elIs():
When it returns
true, the function narrowsel's type by ruling outnull(if applicable) and intersecting with{ tagName: T }, whereTis the string-literal type provided as thetagNameargument. So if theelyou supply has typeHTMLElement(orHTMLElement | null), then ifelIs(el, 'DIV')returnstrue, the type ofelwill be narrowed toHTMLElement & { tagName: 'DIV' }.You get autocomplete functionality and typo-prevention with the
tagNameparameter.Specifically, the
tagNameparameter must be the value of a standard DOM element'stagNameproperty, and this restriction further depends on the type of theelargument you supply. For example, ifelis an instance ofHTMLElement, then the suppliedtagNameargument must be the value of a standard HTML element'stagNameproperty, like'DIV'. Supportedeltypes areHTMLElement,SVGElement,MathMLElement, the more generalElement, and unions of any of these; thetagNameargument will always be appropriately restricted. (It's best, though, ifelis justHTMLElement,SVGElement, orMathMLElement, so that you don't have to worry about confusing uppercase HTML tag-names like'A'with lowercase SVG or MathML tag-names like'a'.)
If you don't use elIs(), you can just do something like if (el.matches('section')) or if (el.tagName === 'section') instead. But then you don't get the type-narrowing, the autocomplete, or the typo-prevention, and you'll probably make the mistake I made in the previous sentence (should be if (el.tagName === 'SECTION')).
A few more notes:
- Because of the
tagNamerestrictions, this function won't work with custom elements in TypeScript. - Although
SVGElementis a supported type for theelparameter, it's worth noting that, at the time of writing, every kind of SVG element has its own dedicated interface (likeSVGPathElement), so you probably want to reach forinstanceofwith SVG tags. - Deprecated HTML elements are supported (e.g., if
elis anHTMLElement, thentagNamecan be'MARQUEE').
