Pattern di immutabilità profonda
Ottenga strutture profondamente readonly con tipi ricorsivi.
Pattern di immutabilità profonda è una lezione TypeScript Academy gratuita su CoddyKit. Questa è la lezione 4 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento TypeScript Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso TypeScript Academy include 4 lezioni in totale.
Immutabilità superficiale e profonda
Il modificatore readonly è superficiale: protegge il livello superiore, ma non gli oggetti annidati. L'immutabilità profonda significa che ogni livello, fino in fondo, è readonly. Per ottenerla è necessario del lavoro aggiuntivo.
interface State { readonly user: { name: string }; }
const s: State = { user: { name: 'Ada' } };
// s.user = {...}; // Error (shallow protection)
s.user.name = 'Grace'; // allowed! nested field is mutable
console.log(s.user.name);Perché la protezione superficiale non basta
Per la gestione dello stato e dei dati condivisi, readonly superficiale lascia esposti i campi annidati. Una singola mutazione sfuggita in profondità in una struttura può causare bug sottili e difficili da ricondurre all'origine.
interface Config { readonly db: { host: string; port: number }; }
const c: Config = { db: { host: 'localhost', port: 5432 } };
c.db.port = 9999; // mutates nested data despite readonly
console.log(c.db.port);Un tipo DeepReadonly ricorsivo
Possiamo creare un mapped type che applichi readonly in modo ricorsivo. DeepReadonly<T> attraversa ogni proprietà e, se è un oggetto, ricorre al livello successivo.
type DeepReadonly<T> = {
readonly [K in keyof T]: T[K] extends object
? DeepReadonly<T[K]>
: T[K];
};
console.log('DeepReadonly defined');Applicare DeepReadonly
Racchiudere un tipo in DeepReadonly rende immutabili anche le proprietà annidate. Ora non è possibile riassegnare neppure s.user.name: la protezione arriva fino in fondo.
type DeepReadonly<T> = {
readonly [K in keyof T]: T[K] extends object
? DeepReadonly<T[K]>
: T[K];
};
type State = DeepReadonly<{ user: { name: string } }>;
const s: State = { user: { name: 'Ada' } };
// s.user.name = 'x'; // Error now
console.log(s.user.name);Come funziona il mapped type
[K in keyof T] itera su ogni chiave. Il prefisso readonly blocca ciascuna di esse. La condizione T[K] extends object ? ... : T[K] decide se ricorrere o fermarsi a un tipo primitivo.
type DeepReadonly<T> = {
readonly [K in keyof T]: T[K] extends object
? DeepReadonly<T[K]>
: T[K];
};
type Cfg = DeepReadonly<{ a: number; b: { c: string } }>;
const cfg: Cfg = { a: 1, b: { c: 'x' } };
console.log(cfg.a, cfg.b.c);Protezione solo in fase di compilazione
DeepReadonly impone l'immutabilità nel sistema dei tipi, non durante l'esecuzione. L'oggetto JavaScript è ancora tecnicamente modificabile attraverso percorsi privi di tipi, ma il codice tipizzato è completamente protetto.
// Type-level immutability does not freeze the runtime object.
// For runtime guarantees, combine it with Object.freeze.
console.log('Types guard your code; freeze guards runtime');Congelare gli oggetti annidati durante l'esecuzione
Per ottenere l'immutabilità effettiva durante l'esecuzione, utilizzi Object.freeze. Impedisce di aggiungere, rimuovere o modificare proprietà, ma, come readonly, per impostazione predefinita agisce solo superficialmente.
const config = Object.freeze({ host: 'localhost', port: 8080 });
console.log(config.port);
// In strict mode, config.port = 1 throws; otherwise silently ignored.Un helper per il congelamento profondo
Per congelare in profondità durante l'esecuzione, ricorra attraverso gli oggetti annidati e congeli ciascuno di essi. Questo si abbina naturalmente a DeepReadonly a livello di tipo, per ottenere un'immutabilità completa.
function deepFreeze<T>(obj: T): T {
Object.values(obj as any).forEach((v) => {
if (v && typeof v === 'object') deepFreeze(v);
});
return Object.freeze(obj);
}
const frozen = deepFreeze({ a: { b: 1 } });
console.log(frozen.a.b);Immutabilità per uno stato più sicuro
L'immutabilità profonda è alla base di uno stato prevedibile. Quando i dati non possono essere modificati sul posto, gli aggiornamenti devono creare nuovi oggetti, rendendo le modifiche esplicite e facili da monitorare.
const state = { count: 0, user: { name: 'Ada' } };
// Immutable update: create a new object instead of mutating
const next = { ...state, count: state.count + 1 };
console.log(state.count, next.count);Modello degli aggiornamenti immutabili
Con i dati readonly, produce nuove versioni usando lo spread. Ogni aggiornamento crea un nuovo oggetto, quindi gli stati precedenti rimangono intatti: una caratteristica preziosa per l'annullamento, il debug tramite viaggio nel tempo e il rilevamento delle modifiche.
type State = { readonly items: readonly string[] };
const s: State = { items: ['a'] };
const updated: State = { items: [...s.items, 'b'] };
console.log(s.items, updated.items);Combinare sicurezza dei tipi e dell'esecuzione
L'approccio più solido utilizza entrambi: DeepReadonly per le garanzie in fase di compilazione e deepFreeze per l'applicazione durante l'esecuzione. Insieme rendono quasi impossibili le mutazioni accidentali.
function freeze<T>(obj: T): T {
return Object.freeze(obj);
}
const settings = freeze({ theme: 'dark', version: 2 });
console.log(settings.theme, settings.version);Verifica rapida
Verifichi la Sua comprensione dell'immutabilità profonda.
Riepilogo: immutabilità profonda
Ha imparato che:
readonlyè superficiale: i campi annidati restano modificabili.- Un mapped type ricorsivo
DeepReadonly<T>applica readonly a ogni livello. - Esiste solo in fase di compilazione; utilizzi
Object.freezein profondità per imporre l'immutabilità durante l'esecuzione. - L'immutabilità consente di gestire lo stato in modo sicuro e prevedibile tramite modelli di copia e aggiornamento.
Con questo si conclude il percorso di TypeScript Academy sui tipi avanzati e l'immutabilità.
type State = { readonly value: number };
const s: State = { value: 1 };
const next: State = { ...s, value: s.value + 1 };
console.log(s.value, next.value);Domande Frequenti
La lezione «Pattern di immutabilità profonda» è gratuita?
Sì — il testo completo di «Pattern di immutabilità profonda» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso TypeScript Academy, passa a CoddyKit PRO. Il corso TypeScript Academy include 4 lezioni in totale.
Cosa imparerò in «Pattern di immutabilità profonda»?
Ottenga strutture profondamente readonly con tipi ricorsivi. Eserciti TypeScript Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare TypeScript Academy?
Non è richiesta alcuna esperienza precedente. TypeScript Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 4 di 4.
Quanto tempo richiede la lezione «Pattern di immutabilità profonda»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione TypeScript Academy?
Sì. Ogni lezione TypeScript Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Proprietà readonly
- Array e tuple readonly
- ReadonlyArray e ReadonlyMap
- Pattern di immutabilità profonda