What is the best way to select elements by class name in TypeScript?

I've been experimenting with trying to retrieve elements by class name from the DOM using TypeScript. Despite what seems like a straightforward approach, I'm encountering an error in the console.

function showSlides() {
   var i;
   var slides = <HTMLElement[]<any>document.getElementsByClassName('slide');

   for (i = 0; i < slides.length; i++) {
     slides[i].style.display = "none";
   }
}

Expected behavior is to have an array with 3 items and to change the display style to none, however the actual outcome is a JS error:

Uncaught TypeError: Cannot read property 'style' of undefined.

Answer №1

document.getElementsByClassName function retrieves a collection of HTMLCollection containing Element objects.

These Elements can vary in types, with HTMLElement and SVGElement being among them.

If you are certain that all the elements returned are of type HTMLElement, you can explicitly cast them as such.

const showSlides = () => {
    const slides = document.getElementsByClassName('slide');

    for (let i = 0; i < slides.length; i++) {
        const slide = slides[i] as HTMLElement;
        slide.style.display = "none";
    }
};

If there is a chance of non-HTMLElement elements being returned, you will need to implement a method to identify and handle them.

One approach to achieve this could be:

const showSlides = () => {
    const slides = document.getElementsByClassName('slide');

    for (let i = 0; i < slides.length; i++) {
        const slide = slides[i];

        if (slide instanceof HTMLElement) {
            // slide is a HTMLElement
            slide.style.display = "none";
        } else if (slide instanceof SVGElement) {
            // slide is a SVGElement
            const svgOwner = slide.ownerSVGElement;
        } else {
            // slide is a Element
            const baseUri = slide.baseURI;
        }
    }
};

Answer №2

It took me a little while, but I've grappled with this issue too.

const slides = Array.from(document.getElementsByClassName('slide'));

for (const x of slides) {
    const y = <HTMLElement> x;
    y.style.display = 'none';
}

I believe this solution should do the trick.

For more information on the for of loop, check out https://www.typescriptlang.org/docs/handbook/iterators-and-generators.html

If you're using TypeScript, it's recommended to avoid the traditional JavaScript way of looping through an array and instead opt for the TypeScript method.

The getElementsByClassName method returns an array of elements. However, you can't apply styles directly to an Element - it must be a HTMLElement. By wrapping the getElementsByClassName in Array.from, it will return an array of Elements. You can then iterate through this Element array in the for loop, casting each object as a HTML element array to utilize .style on them.

If you have any questions, feel free to reach out to me.

Answer №3

The style property is specifically designed for use with instances of HTMLElement, but the slides collection consists of a wider type: Element.

To safely adjust the style of each element, it is important to verify if the element is indeed an HTMLElement before making any changes.

function showSlides() {
  var i;
  var slides = document.getElementsByClassName('slide');

  for (i = 0; i < slides.length; i++) {
    const slide = slides[i];

    if (slide instanceof HTMLElement) {
      slide.style.display = "none";
    }
  }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Generic type array does not display property

I feel like I must be overlooking something. It seems too straightforward to be causing issues for me. Database.ts export class Database { id: number; } search-input.ts import { Database } from './../resources/database'; import { Inje ...

Exporting a constant as a default in TypeScript

We are currently developing a TypeScript library that will be published to our private NPM environment. The goal is for this library to be usable in TS, ES6, or ES5 projects. Let's call the npm package foo. The main file of the library serves as an e ...

Share edited collection with Observer

The challenge Imagine creating an Angular service that needs to expose an Observable<number[]> to consumers: numbers: Observable<number[]>; Our requirements are: Receive the latest value upon subscription Receive the entire array every tim ...

Unable to locate template while working with Angular 2 in ASP MVC framework

I am currently utilizing angular 2 within ASP.NET MVC. This particular component is referred to as the "other" component: import { Component } from '@angular/core'; @Component({ selector: 'other-app', templateUrl: './app ...

What is the best way to rid ourselves of unwanted values?

In the laravel-vue-boilerplate package, there is a User CRUD feature. I duplicated this functionality to create an Item CRUD by making some changes and adjustments. Everything is working fine except for one issue: after editing an item, when trying to add ...

Managing Authorization Errors in FirebaseListObservable

My current challenge involves trying to detect an authorization error from Firebase/AngularFire by utilizing the catch method. However, I encounter an issue with the error message stating Property 'catch' does not exist on type 'FirebaseList ...

Retrieve data from a web api at regular intervals using Angular observables and subscription

My Launch method is designed to start an engine by taking parameters and returning the instance name once started. After that, I need to periodically query another service every 2 seconds to check if the status has changed to either "Succeeded" or "Faile ...

What causes the discrepancy in results between these two NodeJS/Typescript imports?

Within my NodeJS project, I have integrated typescript version 3.2 alongside express version 4.16 and @types/express version 4.16. My development is focused on using Typescript with the intention of transpiling it later on. The guidelines for @types/expre ...

Creating asynchronous JavaScript constructors using a static method called "create" presents challenges when dealing with TypeScript types

I've been diving into the world of asynchronous constructors and have successfully implemented them in JavaScript. However, I'm facing a challenge with TypeScript types. Here's how it should ideally work: const a: AnyClass = await AnyClass. ...

Inspect the TypeScript typings within Svelte documents directly from the terminal

When I run tsc --noemit, it successfully checks for type errors in the codebase. However, I have encountered an issue where it does not seem to check .svelte files. Is there a way to enable this functionality? I can see the type errors in .svelte files wh ...

What is the best way to hand off this object to the concatMap mapping function?

I'm currently in the process of developing a custom Angular2 module specifically designed for caching images. Within this module, I am utilizing a provider service that returns Observables of loaded resources - either synchronously if they are already ...

SignalR 2.2 application encountering communication issues with client message reception

I am facing an issue in my application where clients are not receiving messages from the Hub when a user signs in. Here is my Hub class: public class GameHub : Hub { public async Task UserLoggedIn(string userName) { aw ...

Using ThreeJS to Apply Dual Materials to a Mesh Entity

With ThreeJS, it's possible to incorporate more than one material into an Object3D/Mesh as stated in the documentation. You can either utilize a single Material or an array of Material: Class declaration and constructor for Mesh TypeScript file (exce ...

Encountering error TS2307: Module 'redux' not found when trying to implement redux in Angular 7

Currently, I am diving into the world of Redux and attempting to integrate it into my Angular 7 project using ng2-redux. However, upon visiting the npm page, I discovered that the recommended approach was to install it with npm install @angular-redux/store ...

Search for records in MySQL using Typeorm with the condition "column like %var%" to retrieve results containing the specified

Looking for a way to search in MySql using typeorm with the "column like" functionality. async findAll({ page, count, ...where }: CategorySelectFilter): Promise<Category[]> { return this.categoryRepository.find({ where, ...

Determine if the "type" field is optional or mandatory for the specified input fields in Typescript

I need to determine whether the fields of a typescript type or interface are optional or required. export type Recommendation = { id?: string, name: string, type?: string, tt: string, isin?: string, issuer: string, quantity?: nu ...

Custom type declaration file in Typescript fails to function properly

I have searched through countless solutions to a similar issue, but none seem to work for me. I am attempting to utilize an npm package that lacks TypeScript type definitions, so I decided to create my own .d.ts file. However, every time I try, I encounter ...

Error message TS2339: The method 'findAll' is not defined in the current context

Despite following the Sequelize guide for TypeScript configuration, I am unable to resolve an issue with my database connection. The connection is active, but I am struggling with a specific type problem: TSError: ⨯ Unable to compile TypeScript: controll ...

What could be causing TypeScript to struggle with verifying the return type of a function?

I am facing an issue with a function that is supposed to return NetworkState. However, despite the code clearly showing that the function does not return the correct type in most cases, TypeScript does not flag any errors. Can someone point out what I migh ...

Mismatched data types caused by immutability

I'm having trouble with my object that has a middleware property and the types aren't working as expected. The error message is stating that the two middlewares are incompatible because one of them is set to readonly. Does anyone know how I can r ...