Patronen voor diepe onveranderlijkheid
Bereik diepgaand readonly structuren met recursieve typen
Patronen voor diepe onveranderlijkheid is een gratis TypeScript Academy-les op CoddyKit. Dit is les 4 van 4. Je kunt de volledige les hieronder gratis lezen en daarna in de browser praktisch oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject TypeScript Academy. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus TypeScript Academy bevat in totaal 4 lessen.
Oppervlakkige versus diepe onveranderlijkheid
De modifier readonly is oppervlakkig: hij beschermt het bovenste niveau, maar niet geneste objecten. Diepe onveranderlijkheid betekent dat elk niveau, helemaal tot onderaan, readonly is. Daar is extra werk voor nodig.
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);Waarom oppervlakkig niet genoeg is
Voor toestandsbeheer en gedeelde gegevens laat oppervlakkige readonly geneste velden onbeschermd. Eén gemiste wijziging diep in een structuur kan subtiele, moeilijk te traceren fouten veroorzaken.
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);Een recursief DeepReadonly-type
We kunnen een gemapt type bouwen dat readonly recursief toepast. DeepReadonly<T> doorloopt elke eigenschap en gaat, als die een object is, daarin verder.
type DeepReadonly<T> = {
readonly [K in keyof T]: T[K] extends object
? DeepReadonly<T[K]>
: T[K];
};
console.log('DeepReadonly defined');DeepReadonly toepassen
Door een type in DeepReadonly te wikkelen, worden ook geneste eigenschappen onveranderlijk. Nu kan zelfs s.user.name niet opnieuw worden toegewezen — de bescherming reikt helemaal tot onderaan.
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);Zo werkt het gemapte type
[K in keyof T] doorloopt elke sleutel. Het voorvoegsel readonly vergrendelt elke sleutel. De voorwaardelijke expressie T[K] extends object ? ... : T[K] bepaalt of er verder wordt gegaan of bij een primitieve waarde wordt gestopt.
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);Bescherming die alleen tijdens compilatie werkt
DeepReadonly dwingt onveranderlijkheid af in het typesysteem, niet tijdens uitvoering. Het JavaScript-object kan technisch gezien nog steeds worden gewijzigd via paden zonder typen — maar je getypecode is volledig beschermd.
// 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');Geneste objecten tijdens uitvoering vergrendelen
Gebruik Object.freeze voor echte onveranderlijkheid tijdens uitvoering. Hiermee voorkom je dat eigenschappen worden toegevoegd, verwijderd of gewijzigd — maar net als readonly werkt dit standaard oppervlakkig.
const config = Object.freeze({ host: 'localhost', port: 8080 });
console.log(config.port);
// In strict mode, config.port = 1 throws; otherwise silently ignored.Een helper voor diep vergrendelen
Om tijdens uitvoering alles diep te vergrendelen, loop je recursief door geneste objecten en vergrendel je elk object. Dit combineert natuurlijk met het type DeepReadonly voor onveranderlijkheid van begin tot eind.
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);Onveranderlijkheid voor veiligere toestand
Diepe onveranderlijkheid vormt de basis voor voorspelbare toestand. Wanneer gegevens niet ter plaatse kunnen worden gewijzigd, moeten updates nieuwe objecten maken, waardoor wijzigingen expliciet en eenvoudig te volgen zijn.
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);Patroon voor onveranderlijke updates
Met readonly-gegevens maak je nieuwe versies via de spread-syntaxis. Elke update is een nieuw object, zodat eerdere toestanden intact blijven — onmisbaar voor ongedaan maken, foutopsporing met tijdreizen en het detecteren van wijzigingen.
type State = { readonly items: readonly string[] };
const s: State = { items: ['a'] };
const updated: State = { items: [...s.items, 'b'] };
console.log(s.items, updated.items);Type- en uitvoeringsveiligheid combineren
De sterkste aanpak gebruikt beide: DeepReadonly voor garanties tijdens compilatie en deepFreeze voor afdwinging tijdens uitvoering. Samen maken ze onbedoelde wijzigingen vrijwel onmogelijk.
function freeze<T>(obj: T): T {
return Object.freeze(obj);
}
const settings = freeze({ theme: 'dark', version: 2 });
console.log(settings.theme, settings.version);Korte test
Test je begrip van diepe onveranderlijkheid.
Herhaling: diepe onveranderlijkheid
Je hebt geleerd dat:
readonlyoppervlakkig is; geneste velden blijven wijzigbaar.- Een recursief gemapt type
DeepReadonly<T>readonly op elk niveau toepast. - Het alleen tijdens compilatie werkt; gebruik
Object.freeze(recursief) voor afdwinging tijdens uitvoering. - Onveranderlijkheid veilige, voorspelbare toestand mogelijk maakt via patronen waarbij je bij elke update een kopie maakt.
Daarmee is het TypeScript Academy-traject over geavanceerde typen en onveranderlijkheid voltooid.
type State = { readonly value: number };
const s: State = { value: 1 };
const next: State = { ...s, value: s.value + 1 };
console.log(s.value, next.value);Leer TypeScript met een AI-tutor — gratis
Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.
- Cursussen
- 101
- Lessen
- 352
Veelgestelde vragen
Is de les “Patronen voor diepe onveranderlijkheid” gratis?
Ja — de volledige tekst van “Patronen voor diepe onveranderlijkheid” kun je hier gratis op het web lezen. Als je interactief wilt oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is, en de rest van de cursus TypeScript Academy wilt ontgrendelen, kun je upgraden naar CoddyKit PRO. De cursus TypeScript Academy bevat in totaal 4 lessen.
Wat leer ik in “Patronen voor diepe onveranderlijkheid”?
Bereik diepgaand readonly structuren met recursieve typen Je oefent met TypeScript Academy door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.
Heb ik ervaring nodig om met TypeScript Academy te beginnen?
Ervaring vooraf is niet nodig. TypeScript Academy op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 4 van 4.
Hoe lang duurt de les “Patronen voor diepe onveranderlijkheid”?
De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.
Kan ik code schrijven en uitvoeren in deze les over TypeScript Academy?
Ja. Elke les over TypeScript Academy bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.
Alle lessen in deze cursus
- readonly-eigenschappen
- readonly-arrays en tuples
- ReadonlyArray en ReadonlyMap
- Patronen voor diepe onveranderlijkheid