ProgrammazioneSviluppatore Backend

Come funziona il meccanismo di tipizzazione delle proprietà statiche e dei metodi statici in TypeScript, quali sono le peculiarità nella definizione dei loro tipi e qual è la differenza rispetto alla tipizzazione degli elementi non statici della classe?

Supera i colloqui con l'assistente IA Hintsage

Risposta.

Storia della questione:

Le proprietà e i metodi statici sono apparsi nelle classi JavaScript a partire da ES6, tuttavia la tipizzazione rigorosa di questi elementi è diventata possibile grazie a TypeScript. Nel JavaScript dinamico, gli elementi statici della classe non si differenziano per tipo da quelli non statici, ma TypeScript consente di aggiungere sicurezza di tipo e struttura delle classi tenendo conto dei membri statici.

Problema:

Le proprietà e i metodi statici appartengono alla classe stessa, non alle sue istanze. Tuttavia, molti sviluppatori confondono la tipizzazione dell'istanza (tramite this o il costruttore) e la tipizzazione della classe stessa come oggetto. Questo porta talvolta a errori quando si accede ai campi statici all'interno dei metodi o durante l'ereditarietà.

Soluzione:

In TypeScript, i membri statici delle classi vengono tipizzati separatamente dai membri non statici:

  • Per i membri non statici si utilizza la descrizione tramite il corpo della classe.
  • Per i membri statici — tramite la parola chiave static.
  • Il tipo della classe stessa può essere descritto usando la costruzione typeof, per passarlo e utilizzarlo in modo sicuro come oggetto con una struttura definita.

Esempio di codice:

class User { static count: number = 0; name: string; constructor(name: string) { this.name = name; User.count++; } static getCount(): number { return User.count; } } function createUserClass(): typeof User { return User; }

Caratteristiche chiave:

  • I membri statici non vivono nell'istanza, ma nel costruttore della classe, quindi sono accessibili solo tramite la classe stessa
  • Per passare/tipizzare la classe stessa si usa typeof User, mentre per le istanze — User
  • I metodi statici hanno le loro limitazioni (nessun accesso a this, a meno che non vengano chiamati tramite il costruttore della classe)

Domande insidiose.

Possono i metodi statici lavorare direttamente con le proprietà non statiche della classe?

No, i metodi statici non hanno accesso alle proprietà non statiche tramite this, poiché this si riferisce alla classe stessa (costruttore). Per lavorare con le proprietà non statiche è necessario operare con le istanze dell'oggetto.

class Demo { static demoStatic() { // this.value; // Errore — value non è static } }

È possibile accedere a una proprietà static attraverso un'istanza della classe?

No, l'accesso alle proprietà statiche è possibile solo tramite il nome della classe stessa, non tramite l'istanza:

const u = new User('Max'); console.log(u.count); // Errore console.log(User.count); // OK

È possibile ereditare e sovrascrivere metodi statici durante l'ereditarietà della classe?

Sì, i metodi statici possono essere ereditati e sovrascritti, e questo funzionerà come previsto:

class Animal { static who() { return 'Animal'; } } class Dog extends Animal { static who() { return 'Dog'; } } console.log(Dog.who()); // 'Dog'

Errori tipici e anti-pattern

  • Confusione tra membri statici e non statici della classe
  • Tentativo di accedere ai campi statici tramite un'istanza
  • Errori nell'uso di this all'interno dei metodi static

Esempio dalla vita reale

Caso negativo

Un sviluppatore memorizza un contatore di istanze create come una normale proprietà di istanza, invece che come statico. Ad ogni creazione di un oggetto, il campo aumenta, ma non è sincronizzato per tutti gli oggetti della classe.

Pro:

  • Facile da implementare senza conoscenze su static

Contro:

  • Violazione delle invarianti, il contatore non riflette il numero di oggetti, possibilità di errori durante la creazione in massa

Caso positivo

Utilizzo di static count per tenere traccia di tutti gli oggetti, aumento corretto nel costruttore e metodo statico per ottenere il contatore.

Pro:

  • Garanzia di tracciamento corretto, incapsulazione della logica solo nella classe
  • I campi static non possono essere confusi con i campi dell'istanza

Contro:

  • Richiede comprensione della differenza tra static e instance, è necessario ricordare la sintassi