Using getElementByClassName() method in TypeScript

Updated: February 14, 2024 By: Guest Contributor Post a comment

Introduction

TypeScript enhances JavaScript by adding types, thus providing better tooling at compile time. When interacting with the DOM using TypeScript, understanding how to work with types explicitly can optimize your web development process and help catch errors early. The getElementsByClassName() method is a powerful tool for manipulating HTML elements based on their class name in a typed context, let’s dive into how to use it effectively.

Basic Example: Accessing Elements

First, let’s look at a simple example of using getElementsByClassName() to change the background color of all elements with the class highlight. Assume our HTML contains multiple elements with this class:

<div class="highlight">Item 1</div>
<div class="highlight">Item 2</div>
<div class="highlight">Item 3</div>

In TypeScript, you might try to access these elements as follows:

const highlights = document.getElementsByClassName('highlight');
for (let i = 0; i < highlights.length; i++) {
  const element = highlights[i] as HTMLElement;
  element.style.backgroundColor = 'yellow';
}

This code demonstrates a basic use of type assertion (`as HTMLElement`) to manipulate the style of the retrieved elements. TypeScript understands that each item in the HTMLCollection is an element, but we specify `HTMLElement` to access style properties safely.

Intermediate Example: Integrating with Type Assertions

As you become more comfortable with the basics, you might encounter scenarios where elements fetched with getElementsByClassName() are not necessarily of the same type. For example, suppose your HTML has both div and p tags with the class highlight:

<div class="highlight">Box 1</div>
<p class="highlight">Paragraph 1</p>

When manipulating these elements in TypeScript, a more refined approach is needed:

const highlights = document.getElementsByClassName('highlight');
Array.from(highlights).forEach((element) => {
  if (element instanceof HTMLElement) {
    element.style.color = 'blue';
  }
});

This code snippet leverages Array.from() to create a static array from the live HTMLCollection, which allows us to use the forEach method. The instanceof check assures TypeScript that our operations are performed on instances of HTMLElement, making our code type-safe and flexible.

Advanced Example: Generics and Custom Types

In more complex scenarios, you may want to use the getElementsByClassName() method in functions that are generic or work with custom types. For instance, creating a generic function that applies a style to all elements with a specific class but could also return the elements as a typed array for further manipulation:

type ElementWithStyle = HTMLElement | SVGElement;

function styleElementsByClass<T extends ElementWithStyle>(className: string, style: Partial<CSSStyleDeclaration>): T[] {
  const elements = document.getElementsByClassName(className);
  const styledElements: T[] = [];
  Array.from(elements).forEach((element) => {
    if (element instanceof HTMLElement || element instanceof SVGElement) {
      Object.assign(element.style, style);
      styledElements.push(element as T);
    }
  });
  return styledElements;
}

const styledHighlights = styleElementsByClass<HTMLElement>('highlight', { color: 'red' });

This example introduces a function styleElementsByClass that accepts a class name and a style object, applying the style to elements of that class and returning an array of typed elements. The use of generics (T extends ElementWithStyle) combined with type guards (instanceof) ensures the function is both versatile and type-safe.

Conclusion

The getElementsByClassName() method is a versatile tool for selecting and manipulating DOM elements in TypeScript. By understanding how to use type assertions and type guards, developers can create flexible, type-safe web applications. Whether you’re making minor style adjustments or working with more complex DOM manipulation scenarios, TypeScript’s static typing features can help ensure your code is robust and maintainable.