ProgrammationDéveloppeur Fullstack

Comment fonctionne le mécanisme des champs privés (propriétés privées) dans les classes TypeScript ? Quelles sont les différences entre les propriétés privées utilisant le modificateur private et le symbole #, quelles sont les spécificités de leur utilisation et leurs limitations ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

Historique de la question

Dans TypeScript, les propriétés privées sont initialement apparues grâce au modificateur private, et à partir d'ECMAScript 2021, JavaScript prend en charge de véritables champs privés grâce au symbole #. L'objectif principal est d'encapsuler les données pour protéger les détails internes de la classe contre l'accès externe.

Problème

Le modificateur private dans TypeScript garantit la confidentialité uniquement au moment de la compilation, mais dans le JavaScript compilé, ces champs restent accessibles par un accès direct aux propriétés de l'objet. Cela peut entraîner des modifications non intentionnelles de l'état de l'objet. Les champs privés ES (#) sont complètement inaccessibles en dehors de la classe, même au niveau de l'exécution de JS, ce qui garantit une véritable protection des données.

Solution

TypeScript supporte les deux approches. Lors du choix entre elles, orientez-vous vers le niveau de protection requis et les restrictions de compatibilité avec les versions de JS.

Exemple de code :

class Example { private hidden: number; #trulyHidden: string; constructor() { this.hidden = 42; this.#trulyHidden = 'secret'; } getHidden() { return this.hidden; } getTrulyHidden() { return this.#trulyHidden; } } const x = new Example(); // x.hidden — erreur dans TS, mais fonctionnera via x['hidden'] dans JS // x.#trulyHidden — erreur de syntaxe même dans JS

Caractéristiques clés :

  • private garantit la confidentialité uniquement au moment de la compilation TypeScript
  • #field offre une véritable confidentialité au niveau de l'exécution JavaScript
  • L'utilisation de # nécessite le support du JS moderne (ES2021+)

Questions pièges.

Peut-on accéder à un champ privé d'une classe TypeScript par un accès direct en JS ?

Oui, c'est possible, car la confidentialité est mise en œuvre uniquement au moment de la compilation. Dans le JS source, le champ sera une propriété normale de l'objet. Par exemple :

class A { private x = 1; } const a = new A(); console.log((a as any)["x"]); // 1

Peut-on utiliser des champs privés avec # dans des interfaces ou les décrire à l'aide de type ?

Non, les champs #private font uniquement partie de l'implémentation de la classe et ne peuvent pas être décrits dans des interfaces, des types ou utilisés en dehors de la classe elle-même. Les interfaces décrivent uniquement les membres publics.

Peut-on hériter des champs privés déclarés à l'aide de # ?

Non, ces champs ne sont pas accessibles par les classes dérivées. Seule la classe elle-même a accès à ces champs :

class Parent { #foo = 123; } class Child extends Parent { // this.#foo = 444; // Erreur }

Erreurs typiques et anti-patterns

  • Utiliser private pour protéger des données critiques — cela entraîne des vulnérabilités lors d'un accès direct
  • Confusion entre la confidentialité au niveau des types et au niveau d'exécution
  • Essayer d'utiliser #fields dans d'anciennes versions de JS

Exemple de la vie réelle

Cas négatif

Dans un projet de stockage de mots de passe, un champ private password est utilisé dans la classe User. Un des développeurs accède accidentellement à través user['password'] pour déboguer, et le champ se retrouve modifié par un module externe.

Avantages :

  • Intégration simple avec TypeScript

Inconvénients :

  • Aucune protection réelle en temps d'exécution JS
  • Facile à contourner la confidentialité par accident

Cas positif

Le développeur utilise le champ privé ES #password. Maintenant, les tentatives d'accès au champ par indexation ou dans les classes dérivées échouent, la sécurité des données est assurée même avec des bibliothèques et des outils tiers.

Avantages :

  • Véritable confidentialité
  • Protection fiable des propriétés sensibles

Inconvénients :

  • Nécessite le support du JS moderne (non compatible avec ES5)
  • Les champs privés ne sont pas visibles dans les interfaces, ne peuvent pas être redéfinis dans les classes dérivées