Les erreurs sont des objets avec un type
Quand JavaScript lève une erreur, il ne te renvoie pas juste une chaîne de caractères — il te renvoie un objet. Cet objet possède un type (son constructeur) ainsi que quelques propriétés standards : name, message et stack.
err.name est une étiquette courte du genre "TypeError". err.message, c'est la description lisible par un humain. err instanceof TypeError te dit à quelle classe précise tu as affaire. Connaître le type, ça compte : ça t'indique si le problème vient d'une faute de frappe, d'une valeur foireuse, ou d'un code qui n'a même pas été analysé.
Il existe sept types d'erreurs JavaScript natifs. Trois que tu croiseras en permanence, et quatre que tu rencontreras de temps en temps.
SyntaxError : le code n'a pas été analysé
Une SyntaxError signifie que JavaScript n'a même pas réussi à lire ton code. Ce n'est pas vraiment une erreur d'exécution — le moteur échoue pendant le parsing, avant même qu'une seule ligne ne tourne. Impossible d'attraper une SyntaxError avec un try/catch dans le même fichier, parce que le fichier entier est rejeté.
function greet(name {
return "hi, " + name;
}
// SyntaxError: Unexpected token '{'
Accolade manquante, virgule en trop, un return en dehors d'une fonction — tout ce qui casse la grammaire du langage déclenche ce type d'erreur. La seule solution, c'est de corriger le code source. Le seul cas où l'on peut réellement attraper un SyntaxError, c'est lors d'un parsing à l'exécution, comme avec JSON.parse :
JSON.parse reçoit une chaîne à l'exécution, donc ses erreurs de syntaxe peuvent être interceptées. Celles de tes propres fichiers source, non.
ReferenceError : ce nom n'existe pas
Une ReferenceError survient quand tu fais référence à une variable qui n'a été déclarée dans aucune portée visible depuis le code en cours d'exécution.
Dans 90 % des cas, c'est une faute de frappe (totl au lieu de total). Les 10 % restants, c'est un problème de portée : tu essaies d'utiliser quelque chose qui a été déclaré dans une autre fonction ou un autre module.
Il y a une cause plus subtile : la temporal dead zone (zone morte temporelle). Les déclarations avec let et const existent dès le début de leur bloc, mais tu ne peux pas y accéder avant la ligne qui les déclare :
x existe bien en tant que liaison au moment où console.log(x) s'exécute, mais il n'a pas encore été initialisé. D'où la fameuse reference error. Pour corriger, il suffit de déplacer l'accès après la déclaration.
TypeError : la valeur n'avait pas la bonne forme
Un TypeError signifie qu'une valeur existe bel et bien, mais qu'elle n'est pas du type attendu par l'opération. Appeler quelque chose qui n'est pas une fonction, lire une propriété sur null ou undefined, réassigner une const — tout ça, ce sont des TypeError.
« Cannot read properties of null (reading 'name') » est sans doute le message d'erreur le plus fréquent en JavaScript. Pour le corriger, deux options : soit tu t'assures que la valeur existe, soit tu protèges l'accès avec le chaînage optionnel : user?.name.
Les autres variantes de TypeError :
Appeler un nombre comme une fonction, réassigner une const, invoquer une méthode qui n'existe pas — dans tous ces cas, la valeur n'avait pas le bon type pour ce que vous lui demandiez.
RangeError : quand la valeur sort des limites autorisées
La RangeError se déclenche lorsqu'un nombre est techniquement valide, mais hors de la plage acceptée par une opération donnée.
La cause classique, c'est la récursion infinie, qui fait exploser la pile d'appels :
« Maximum call stack size exceeded » veut presque toujours dire qu'une fonction s'appelle elle-même sans condition d'arrêt, ou que deux fonctions se rappellent mutuellement en boucle.
URIError et EvalError : les plus rares
URIError est déclenchée par les fonctions de manipulation d'URI (encodeURI, decodeURIComponent et compagnie) quand on leur passe une entrée mal formée :
EvalError est une relique du passé. Les moteurs JavaScript modernes ne le lèvent plus pour rien — il reste là en tant que constructeur uniquement pour des raisons de compatibilité. Tu peux toujours en créer un à la main, mais tu n'en croiseras jamais un dans du code réel.
La chaîne d'héritage
Tous ces types héritent d'un Error de base. Autrement dit, err instanceof Error renvoie true quel que soit le type précis de l'erreur, ce qui est bien pratique dans un catch générique :
Un bloc catch intercepte tout — y compris les valeurs qui ne sont pas des erreurs si quelqu'un écrit throw "oups". Cette dernière branche a son importance. Il faut toujours filtrer avec instanceof avant de manipuler la valeur capturée comme un objet d'erreur.
Créer une erreur personnalisée en JavaScript
Vous pouvez lancer vous-même n'importe lequel des types intégrés quand votre code détecte un problème. Choisissez le type qui correspond à la nature du souci :
Associer le bon type à la bonne défaillance n'est pas qu'une question d'esthétique : ça permet à l'appelant d'écrire un catch ciblé au lieu de devoir analyser les messages d'erreur à la main.
Créer une erreur personnalisée en JavaScript
Quand les types natifs ne collent pas à ton besoin, il suffit d'étendre Error :
Deux choses à retenir : appelez super(message) pour que la classe Error de base soit correctement initialisée, et définissez this.name pour que les logs affichent le bon label. Les champs personnalisés comme field permettent à l'appelant de réagir à des cas d'échec précis sans avoir à parser des chaînes de caractères.
La suite : console et DevTools
Connaître les types d'erreurs JavaScript, c'est la moitié du chemin — l'autre moitié, c'est savoir lire une stack trace et inspecter l'état du programme pendant qu'il tourne. Les devtools du navigateur (et le debugger de Node) transforment le fameux « ça a planté et j'ai aucune idée pourquoi » en quelques secondes d'inspection. C'est ce qu'on voit juste après.
Questions fréquentes
Quels sont les types d'erreurs natifs en JavaScript ?
JavaScript en embarque sept : Error (la classe de base), SyntaxError, ReferenceError, TypeError, RangeError, URIError et EvalError. Chacun est un constructeur qui produit un objet d'erreur avec les propriétés name, message et stack. En pratique, vous croiserez surtout SyntaxError, ReferenceError et TypeError.
Quelle est la différence entre une SyntaxError et une TypeError ?
Une SyntaxError signifie que le code n'est pas du JavaScript valide : le moteur n'arrive même pas à le parser. Une TypeError, elle, survient à l'exécution : le code a bien été analysé, mais il fait quelque chose d'illégal — appeler quelque chose qui n'est pas une fonction, lire une propriété de null, etc. Une erreur de syntaxe bloque tout le script ; une erreur de type ne se déclenche que lorsque la ligne fautive s'exécute.
Quand est-ce qu'on obtient une ReferenceError en JavaScript ?
Quand vous utilisez un nom qui n'a pas été déclaré, ou quand vous accédez à une variable let/const dans sa temporal dead zone (avant que sa déclaration ne soit exécutée). Les fautes de frappe sont la cause numéro un : consoel.log(x) lève ReferenceError: consoel is not defined. Vérifiez d'abord l'orthographe et la portée.
Peut-on créer ses propres types d'erreurs ?
Oui. Il suffit d'étendre la classe native Error : class ValidationError extends Error { }. Pensez à définir this.name dans le constructeur pour que les logs et les branches catch puissent la reconnaître. Les classes d'erreurs personnalisées deviennent intéressantes dès que différents types d'échecs doivent être traités différemment.