TypeError: 'x' is not iterable

Message

TypeError: 'x' is not iterable (Firefox, Chrome)
TypeError: 'x' is not a function or its return value is not iterable (Chrome)

Type d'erreur

Quel est le problĂšme ?

La valeur passĂ©e comme opĂ©rande droit de for
of ou comme argument d'une fonction telle que Promise.all ou TypedArray.from n'est pas un objet itĂ©rable.  Un objet itĂ©rable peut ĂȘtre un objet itĂ©rable natif tel qu'un objet Array, String ou Map ou le rĂ©sultat d'un gĂ©nĂ©rateur ou un objet qui implĂ©mente le protocole itĂ©rable.

Exemples

Parcourir les propriétés d'un objet

En JavaScript, les objets ne sont pas itérables car ils n'implémentent pas le protocole itérable. On ne peut donc pas utiliser for...of afin d'en parcourir les propriétés.

var obj = { 'France': 'Paris', 'England': 'London' };
for (let p of obj) { // TypeError: obj is not iterable
    // 

}

Si on souhaite utiliser un itérateur pour parcourir les propriétés (leurs noms ou leurs valeurs), on pourra utiliser les méthodes Object.keys ou Object.entries qui fournissent des itérateurs :

var obj = { 'France': 'Paris', 'England': 'London' };
// On parcourt les noms des propriétés
for (let country of Object.keys(obj)) {
    var capital = obj[country];
    console.log(country, capital);
}

for (const [country, capital] of Object.entries(obj))
    console.log(country, capital);

On pourrait Ă©galement utiliser un objet Map :

var map = new Map;
map.set('France', 'Paris');
map.set('England', 'London');
// On parcourt les noms des propriétés
for (let country of map.keys()) {
    let capital = map[country];
    console.log(country, capital);
}

for (let capital of map.values())
    console.log(capital);

for (const [country, capital] of map.entries())
    console.log(country, capital);

Itérer grùce à un générateur

Les générateurs sont des fonctions qui, lorsqu'elles sont appelées, produisent des objets itérables.

function* generate(a, b) {
  yield a;
  yield b;
}

for (let x of generate) // TypeError: generate is not iterable
    console.log(x);

Lorsqu'elles ne sont pas appelĂ©es, l'objet Function correspondant au gĂ©nĂ©rateur peut ĂȘtre appelĂ© mais il n'est pass itĂ©rable. Il ne faut donc pas oublier d'invoquer le gĂ©nĂ©rateur afin de parcourir les valeurs de l'itĂ©rateur qu'il produit.

function* generate(a, b) {
    yield a;
    yield b;
}

for (let x of generate(1,2))
    console.log(x);

Parcourir un itérable spécifique

Les itĂ©rables spĂ©cifiques (custom iterables) peuvent ĂȘtre crĂ©Ă©s en implĂ©mentant la mĂ©thode Symbol.iterator. En implĂ©mentant cette mĂ©thode, il faut s'assurer que la valeur renvoyĂ©e est un objet qui est un itĂ©rateur. Autrement dit, l'objet renvoyĂ© doit possĂ©der une mĂ©thode next().

const monIterableVide = {
    [Symbol.iterator]() {
        return [] // [] est un iterable mais pas un itérateur
                  // car il n'a pas de méthode next
    }
}

Array.from(monIterableVide);  // TypeError: monIterableVide is not iterable

Voici une implémentation correcte :

const monIterableVide = {
    [Symbol.iterator]() {
        return [][Symbol.iterator]()
    }
}

Array.from(monIterableVide);  // []

Voir aussi