Peter Boomsma
Peter Boomsma

Reputation: 9846

Define type in for loop

I have this function:

public hideOtherQuestions() {
    const questionContainers = document.getElementsByClassName('question-container');

    let questionContainer: Element;
    for (let questionContainer in questionContainers) {
        if (!questionContainer.classList.contains('visible')) {
            document.getElementsByClassName('question-container')[0].setAttribute('style', 'display: none');
        }
    }
}

The questionsContainer is an HTMLCollection of Elements. In the for loop the let questionContainer is defined as string.

Because of that I get the error for the if statement that .classList does not exist on string

How do I change the type of the let in the for loop from string to Element?

Upvotes: 0

Views: 76

Answers (2)

Get Off My Lawn
Get Off My Lawn

Reputation: 36351

You want to use of instead of in.

  • in refers to the key which is a string
  • of refers to the value which is your object

So, by taking the following steps:

  1. Wrap your collection in an Array.from()
  2. Change your for from an in to an of

You should then get the results you were expecting

public hideOtherQuestions() {
    const questionContainers = Array.from(document.getElementsByClassName('question-container'));

    let questionContainer: Element;
    for (let questionContainer of questionContainers) {
        if (!questionContainer.classList.contains('visible')) {
            document.getElementsByClassName('question-container')[0].setAttribute('style', 'display: none');
        }
    }
}

Otherwise you will want to set the val in the loop like so:

for (let key in questionContainers) {
  let questionContainer = questionContainers[key]
}

Upvotes: 4

CRice
CRice

Reputation: 32256

The in keyword when used in a loop like that will extract the keys of the object you're iterating on, not the values. Keys of an object are strings, so Typescript is correct in pointing out that error.

Since it's an HTMLCollection, and not a proper array, you can't use a for/of loop either. So you'll be stuck with the old fashioned index loop:

for (let i = 0; i < questionContainers.length; i++) {
    const questionContainer = questionContainers.item(i)
    if (!questionContainer.classList.contains('visible')) {
        document.getElementsByClassName('question-container')[0].setAttribute('style', 'display: none');
    }
}

Or, if you want to use the for/of loop, you might be able to use the Array.from method to transform the collection to a real array:

for (let questionContainer of Array.from(questionContainers)) {
    if (!questionContainer.classList.contains('visible')) {
        document.getElementsByClassName('question-container')[0].setAttribute('style', 'display: none');
    }
}

Upvotes: 1

Related Questions