ProgrammatieFullstack ontwikkelaar

Hoe werkt het mechanisme van Private Fields (privé velden) in TypeScript klassen? Wat is het verschil tussen privé velden met de `private` modifier en met het symbool #, wat zijn de speciale kenmerken en beperkingen van hun toepassing?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord.

Geschiedenis van de vraag

In TypeScript werden privé velden aanvankelijk geïntroduceerd met de modifier private, en sinds ECMAScript 2021 ondersteunt JavaScript echte privé velden met behulp van het symbool #. Het belangrijkste doel is het encapsuleren van gegevens, zodat de interne details van de klasse worden beschermd tegen externe toegang.

Probleem

De private modifier in TypeScript zorgt alleen voor privacy tijdens de compileertijd, maar in de gecompileerde JavaScript blijven deze velden toegankelijk via directe toegang tot de objecteigenschappen. Dit kan leiden tot onbedoelde wijzigingen van de objectstatus. ES Private Fields (#) zijn volledig niet toegankelijk buiten de klasse, zelfs niet op runtime niveau in JS, wat echte gegevensbescherming garandeert.

Oplossing

TypeScript ondersteunt beide benaderingen. Bij het kiezen tussen hen moet u rekening houden met de gewenste mate van bescherming en compatibiliteitsbeperkingen met JS-versies.

Voorbeeldcode:

class Voorbeeld { private verborgen: number; #echtVerbogen: string; constructor() { this.verborgen = 42; this.#echtVerbogen = 'geheim'; } getVerborgen() { return this.verborgen; } getEchtVerbogen() { return this.#echtVerbogen; } } const x = new Voorbeeld(); // x.verborgen — fout in TS, maar werkt via x['verborgen'] in JS // x.#echtVerbogen — syntaxisfout zelfs in JS

Belangrijke kenmerken:

  • private garandeert privacy alleen tijdens de compileertijd van TypeScript
  • #field biedt echte privacy op het niveau van de uitvoering van JavaScript
  • Het gebruik van # vereist ondersteuning voor moderne JS (ES2021+)

Vragen met een valstrik.

Kan men toegang krijgen tot een privé veld van een TypeScript klasse via directe toegang in JS?

Ja, dat kan, omdat de privacy alleen tijdens de compileertijd wordt gerealiseerd. In de originele JS zal het veld een gewone eigenschap van het object zijn. Bijvoorbeeld:

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

Kan men privé velden met # gebruiken in interfaces of deze beschrijven met type?

Nee, #private velden zijn slechts een deel van de implementatie van de klasse en kunnen niet worden beschreven in interfaces of types, of buiten de klasse zelf worden gebruikt. Interfaces beschrijven alleen openbare leden.

Kan men privé velden die met # zijn verklaard, overerven?

Nee, dergelijke velden zijn helemaal niet toegankelijk voor afgeleide klassen. Alleen de eigen klasse heeft toegang tot hen:

class Ouders { #foo = 123; } class Kind extends Ouders { // this.#foo = 444; // Fout }

Typische fouten en anti-patronen

  • Gebruik van private voor het beschermen van cruciale gegevens — leidt tot kwetsbaarheid bij directe toegang
  • Verwarring tussen privacy op het niveau van typen en runtime
  • Pogingen om #fields te gebruiken in oude versies van JS

Voorbeeld uit het leven

Negatief geval

In een project voor het opslaan van wachtwoorden in de User klasse werd het veld private password gebruikt. Een van de ontwikkelaars kreeg per ongeluk toegang via user['password'] voor debugging, en het veld bleek te zijn gewijzigd door een extern module.

Voordelen:

  • Eenvoudige integratie met TypeScript

Nadelen:

  • Geen echte bescherming in runtime JS
  • Gemakkelijk om privacy per ongeluk te omzeilen

Positief geval

Een ontwikkelaar gebruikt het ES-private veld #password. Nu worden pogingen om toegang te krijgen tot het veld via indexing of in afgeleiden klassen niet toegestaan, gegevensbeveiliging is gewaarborgd, zelfs bij het gebruik van externe bibliotheken en tools.

Voordelen:

  • Echte privacy
  • Betrouwbare bescherming van gevoelige eigenschappen

Nadelen:

  • Vereist ondersteuning voor moderne JS (niet compatibel met ES5)
  • Privé velden zijn niet zichtbaar in interfaces, kunnen niet worden overschreven in afgeleiden klassen