Qui es-tu, objet ? Découvrir le nom de la classe en TypeScript (runtime)

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Pourquoi pourriez-vous avoir besoin du nom de la classe en runtime ?

\n\n

Imaginez : vous écrivez un système complexe en TypeScript. Vous avez une hiérarchie de classes — User, Admin, Moderator. Quelque part au fond du code, vous recevez un objet, mais vous ne savez pas qui il est réellement. Vous ne voyez que object dans la console.

\n\n

Ou vous construisez un logger qui doit afficher non pas simplement [Object], mais un nom de classe significatif : [User: John]. Ou vous écrivez un décorateur qui doit décider comment traiter un objet en fonction de son type.

\n\n

C'est là qu'intervient la question avec des milliers de vues sur Stack Overflow : "Get an object's class name at runtime". Aujourd'hui, nous ne donnerons pas seulement une réponse, mais nous regarderons sous le capot de TypeScript et JavaScript pour comprendre comment cela fonctionne réellement.

\n\n

Oui, TypeScript est une surcouche de JavaScript. Toute la magie des types disparaît après la compilation. Mais le nom de la classe n'est pas un type, c'est une propriété du prototype. Et il reste avec nous en runtime.

\n\n

La méthode la plus simple : constructor.name

\n\n

Si vous avez déjà cherché cette question sur Google, vous avez probablement vu cette ligne unique :

\n\n
class User {\n  constructor(public name: string) {}\n}\n\nconst user = new User("Alice");\nconsole.log(user.constructor.name); // "User"
\n\n

Ça marche ? Oui. Rapide ? Oui. Mais il y a des nuances qui peuvent vous mordre si vous ne savez pas comment cela fonctionne.

\n\n

Comment cela fonctionne-t-il sous le capot ?

\n\n

Chaque objet en JavaScript a une propriété constructor. C'est une référence à la fonction qui a créé cet objet. Et toute fonction (une classe est aussi une fonction) a une propriété name.

\n\n

Lorsque vous écrivez user.constructor.name, le moteur fait ce qui suit :

\n
    \n
  • Il parcourt la chaîne de prototypes de l'objet user.
  • \n
  • Il trouve la propriété constructor sur User.prototype.
  • \n
  • Il lit name de la fonction constructeur User.
  • \n
\n\n

C'est une opération peu coûteuse, mais elle n'est pas gratuite. Dans la plupart des cas, vous ne le remarquerez même pas.

\n\n

Quand constructor.name ne fonctionne-t-il pas ?

\n\n

Voici un piège classique :

\n\n
const obj = Object.create(null);\nconsole.log(obj.constructor); // undefined\n// console.log(obj.constructor.name); // TypeError!
\n\n

Un objet créé via Object.create(null) n'a pas de prototype. Il n'a pas de constructor. Soyez prudent.

\n\n

Deuxième cas : la minification. Si vous utilisez un bundler (Webpack, Terser) qui renomme les classes, constructor.name peut retourner quelque chose comme t ou e. C'est un problème uniquement pour la production, mais il faut le savoir.

\n\n

Alternative : instanceof et vérifications personnalisées

\n\n

Parfois, vous n'avez pas besoin seulement du nom, mais d'une vérification : "Cet objet est-il une instance de la classe X ?"

\n\n
class Animal {}\nclass Dog extends Animal {}\n\nconst dog = new Dog();\n\nconsole.log(dog instanceof Dog);    // true\nconsole.log(dog instanceof Animal); // true\nconsole.log(dog instanceof Object); // true
\n\n

instanceof fonctionne via la chaîne de prototypes. Il vérifie si Dog.prototype est présent dans la chaîne de prototypes de l'objet dog. Si oui — true.

\n\n

Mais instanceof ne vous donne pas une chaîne avec le nom. Il donne une valeur booléenne. Pour les logs ou la sérialisation, ce n'est pas adapté.

\n\n

Combinaison : vérification + nom

\n\n

Vous pouvez écrire un utilitaire qui vérifie d'abord le type, puis retourne le nom :

\n\n
function getClassName(obj: any): string | null {\n  if (obj === null || obj === undefined) return null;\n  if (typeof obj !== 'object' && typeof obj !== 'function') return null;\n\n  // Protection contre Object.create(null)\n  if (!obj.constructor) return 'Object (no prototype)';\n\n  const name                

Blogs

Book Recommendations