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# nécessite le support du JS moderne (ES2021+)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 }
private pour protéger des données critiques — cela entraîne des vulnérabilités lors d'un accès directDans 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 :
Inconvénients :
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 :
Inconvénients :