#câmpuri private în TypeScript

Clase TypeScript 3.8

Câmpurile care încep cu # sunt private și la rulare: nu pot fi citite deloc din afara clasei.

Sintaxă
class A {
    #secret: number = 0;
    #ajutor(): void { ... }
    static #numar = 0;
}

Ce face #câmpuri private

Un nume care începe cu # creează un câmp privat din JavaScript (standard din ES2022). Spre deosebire de private din TypeScript, protecția există și la rulare: câmpul nu apare în Object.keys, JSON.stringify sau la acces cu paranteze pătrate, iar codul din afara clasei nu îl poate citi în niciun fel.

Pot fi private în acest fel câmpurile, metodele, accesorii și membrii statici. Accesul se face mereu cu this.#nume. Verificarea #camp in obiect spune dacă obiectul a fost creat de clasa respectivă (este un fel de instanceof mai strict).

Câmpurile # nu se moștenesc în sensul obișnuit: o clasă derivată nu le vede. Nu le poți combina cu private/public pe același membru. Folosește # când datele chiar nu trebuie atinse din afară (de exemplu în biblioteci) și private când îți ajunge verificarea la compilare.

Exemple

Exemplul 1: Câmp privat la rulare

#sold nu apare la afișare sau în JSON.

class Portofel {
    #sold = 0;
    readonly titular: string;

    constructor(titular: string) {
        this.titular = titular;
    }

    adauga(lei: number): this {
        this.#sold += lei;
        return this;
    }

    get sold(): number {
        return this.#sold;
    }
}

const p = new Portofel("Ana").adauga(50).adauga(25);
console.log(p.sold);
console.log(p, JSON.stringify(p), Object.keys(p));

Rezultat

75
Portofel { titular: 'Ana' } {"titular":"Ana"} [ 'titular' ]

Exemplul 2: Metodă privată și verificarea cu in

class Parola {
    #hash: string;
    constructor(text: string) {
        this.#hash = Parola.#calculeaza(text);
    }
    static #calculeaza(text: string): string {
        return [...text].reverse().join("") + text.length;
    }
    static esteParola(x: object): x is Parola {
        return #hash in x;
    }
    verifica(text: string): boolean {
        return this.#hash === Parola.#calculeaza(text);
    }
}

const p = new Parola("iasi2026");
console.log(p.verifica("iasi2026"), p.verifica("cluj"));
console.log(Parola.esteParola(p), Parola.esteParola({ hash: "x" }));

Rezultat

true false
true false

Exemplul 3: Acces din afara clasei

class Portofel {
    #sold = 0;
    adauga(lei: number) {
        this.#sold += lei;
    }
}
const p = new Portofel();
p.adauga(10);
console.log(p.#sold);

Eroarea afișată de tsc

exemplu.mts(9,15): error TS18013: Property '#sold' is not accessible outside class 'Portofel' because it has a private identifier.

Greșeli frecvente

  • Încerci să citești this.#camp dintr-o clasă derivată. Câmpul aparține doar clasei care l-a declarat; folosește protected dacă derivatele au nevoie de el.
  • Folosești #camp cu un target vechi (sub ES2015). tsc dă eroare; câmpurile private au nevoie de WeakMap, disponibil de la ES2015.

Comenzi înrudite

  • public, private, protected: Modificatorii de acces spun cine poate folosi un câmp sau o metodă: oricine, doar clasa sau și clasele derivate.
  • class: Clasele din JavaScript, cu tipuri pe câmpuri, constructor și metode, plus modificatori de acces și interfețe.
  • accesori get/set: Proprietăți calculate: get rulează cod la citire, set rulează cod la scriere, dar se folosesc ca un câmp.
  • static: Membrii static aparțin clasei, nu fiecărui obiect: se folosesc cu NumeClasa.membru.