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:
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 } }
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.