C'est de très loin l'erreur la plus rencontrée en JavaScript, et son message est souvent lu de travers. Elle ne dit pas que le code est faux, elle dit qu'une valeur n'était pas celle attendue à cet endroit.
Autrement dit, le problème vient presque toujours d'ailleurs : de la ligne qui a produit la valeur, pas de la ligne qui a cassé.
Définition
Un TypeError est levé quand une opération porte sur une valeur dont le type ne la permet pas : lire une propriété sur null, appeler ce qui n'est pas une fonction, parcourir ce qui n'est pas parcourable.
const utilisateur = null;
try {
console.log(utilisateur.nom);
} catch (err) {
console.log(err.name); // TypeError
console.log(err.message); // Cannot read properties of null (reading 'nom')
}Le message nomme la valeur fautive et la propriété demandée. C'est déjà la moitié du diagnostic : il reste à remonter jusqu'à l'endroit où utilisateur a pris cette valeur.
Les messages qu'on lit le plus
| Message | Ce qui s'est passé |
|---|---|
| Cannot read properties of undefined | Un champ absent, une réponse incomplète, un tableau vide |
| x is not a function | Une faute de frappe, un import manquant, une valeur qui n'est pas ce qu'on croit |
| x is not iterable | Une Destructuration ou un of sur autre chose qu'un tableau |
| Assignment to constant variable | Une réaffectation d'une const |
Ces quatre lignes couvrent l'essentiel de ce que l'on croise en production. Le premier cas est de loin le plus fréquent, et presque toujours lié à une donnée reçue du réseau.
Les éviter plutôt que les attraper
Un TypeError signale un défaut à corriger, pas un cas de figure à rattraper. Deux outils du langage suppriment la classe entière de ces erreurs.
const reponse = { profil: null };
// Plante : Cannot read properties of null
// console.log(reponse.profil.nom);
// Sûr : le chaînage optionnel s'arrête et rend undefined
console.log(reponse.profil?.nom); // undefined
// Sûr, avec une valeur de repli
console.log(reponse.profil?.nom ?? "Anonyme"); // AnonymeLe Chaînage optionnel (?.) coupe court dès qu'une étape vaut null ou undefined, et la Coalescence des nuls (??) fournit le repli. Vérifier la forme des données à l'entrée reste la protection la plus solide.
Le chaînage optionnel se pose sur les valeurs vraiment facultatives, pas partout. Écrit par réflexe sur une donnée qui devrait exister, il transforme un TypeError parlant en un undefined silencieux qui ressortira trois écrans plus loin.
Questions fréquentes
Quelle différence avec un ReferenceError ?
Le ReferenceError porte sur un nom qui n'existe nulle part, le TypeError sur une valeur qui existe mais ne convient pas. Une variable jamais déclarée donne le premier, une variable déclarée valant undefined donne le second dès qu'on lit une propriété dessus.
Faut-il attraper les TypeError ?
Rarement. Un try posé autour d'un TypeError masque un défaut au lieu de le corriger, et le programme continue avec des données incohérentes. Réservez le rattrapage aux échecs attendus, réseau ou saisie utilisateur, et corrigez le reste.
Comment trouver l'origine d'un message trop vague ?
En lisant la pile d'appels de l'erreur, qui donne la suite des fonctions traversées. La ligne signalée est celle qui a cassé, mais la cause se trouve souvent une ou deux entrées plus bas, à l'endroit où la valeur a été construite.