ProgrammatieTypeScript architect

Hoe wordt patroonmatching (pattern matching) geïmplementeerd in TypeScript via discriminated unions? Hoe structuren je de types correct en welke valkuilen zijn er?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord

In TypeScript wordt patroonmatching geïmplementeerd via "discriminated unions" (discriminatieve unies). Aan elk object in de unie wordt een verplichte discriminator-veld (meestal een string, bijvoorbeeld type) toegewezen, waarmee TypeScript de varianten onderscheidt.

Voorbeeld:

type Success = { type: 'success'; data: string }; type Failure = { type: 'failure'; error: string }; type Result = Success | Failure; function handleResult(result: Result) { switch (result.type) { case 'success': // result: Success console.log(result.data); break; case 'failure': // result: Failure console.error(result.error); break; } }

In de switch/case of if op het discriminator-veld "verkleint" TypeScript het type precies naar de juiste variant.

Belangrijkste voordelen:

  • Strikte typisering — je kunt niet naar een niet-bestaand veld verwijzen.
  • Exhaustiveness-check — als niet alle varianten worden afgehandeld, kan er soms een fout optreden (dit kan expliciet worden afgedwongen).

Misleidende vraag

Als je een nieuwe variant toevoegt aan de discriminated union, zal TypeScript dan dwingen om alle switch-case bij te werken om de nieuwe variant te verwerken?

Antwoord: Nee, alleen als je expliciet de verwerking van de "onmogelijk" variant toevoegt. Bijvoorbeeld, gebruik makend van de never-functie:

Voorbeeld:

function assertNever(x: never): never { throw new Error('Onverwachte variant: ' + x); } function handle(r: Result) { switch(r.type) { case 'success': /* ... */; break; case 'failure': /* ... */; break; default: return assertNever(r); // TS geeft een fout als er een nieuw type verschijnt } }

Voorbeelden van echte fouten door onbekendheid met de nuances van het onderwerp.


Verhaal

Na uitbreiding van het type "Result" met een nieuwe variant ('pending') werden in verschillende delen van de applicatie de oude switch-case niet aangepast voor deze case. Als gevolg werkte een deel van de interfaces niet meer. De fout werd pas na een week in productie opgemerkt na de release.


Verhaal

Een poging om discriminated union te gebruiken zonder unieke discriminator (het type-veld werd in twee types gedupliceerd) leidde tot "vervaging" van de types: TypeScript stopte met het nauwkeurig vernauwen van de types, en het werd mogelijk om naar niet-bestaande velden te verwijzen zonder compilatiefout. Verschillende kritieke bugs zijn in productie gegaan.


Verhaal

In een project werd patroonmatching geïmplementeerd via if-else op meerdere velden in plaats van één duidelijke discriminator te gebruiken. Dit bemoeilijkte de overstap naar exhaustiveness-check met de never-functie en verslechterde de leesbaarheid van de code — switch-case werkten niet correct en nieuwe varianten "braken" de bestaande logica.