TypeScript Academy · Les

Patronen voor diepe onveranderlijkheid

Bereik diepgaand readonly structuren met recursieve typen

Les 4 van 413 stappen

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:

  • readonly oppervlakkig 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);
Gratis beginnen

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

  1. readonly-eigenschappen
  2. readonly-arrays en tuples
  3. ReadonlyArray en ReadonlyMap
  4. Patronen voor diepe onveranderlijkheid
← Terug naar TypeScript Academy