ProgrammatieFrontend ontwikkelaar

Leg de mechanica van type-narrowing (Type Narrowing) in TypeScript uit. Welke manieren zijn er om de types van variabelen te versmallen, en waarvoor wordt dit gebruikt?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord.

Type narrowing (Type Narrowing) in TypeScript is het proces waarbij de compiler "begrijpt" dat een variabele in een bepaald stuk code een specifieker type heeft, op basis van voorwaarden.

Typische technieken voor type narrowing:

  • Controle via de typeof operator:
function example(x: number | string) { if (typeof x === 'string') { // x: string hier return x.toUpperCase(); } else { // x: number hier return x.toFixed(2); } }
  • Controle via instanceof (voor klassen):
if (dateObj instanceof Date) { // dateObj: Date }
  • Controle op null en undefined:
function print(value?: string) { if (value != null) { // value: string console.log(value.length); } }
  • Controle met behulp van "discriminant properties" (discriminante eigenschappen):
type Pet = { kind: 'dog'; woof: () => void } | { kind: 'cat'; meow: () => void }; function sound(pet: Pet) { if (pet.kind === 'dog') { pet.woof(); } else { pet.meow(); } }

TypeScript ondersteunt ook gebruikersgedefinieerde type guard functies:

function isString(x: unknown): x is string { return typeof x === 'string'; }

Narrowing maakt typechecks veiliger en de code betrouwbaarder.

Vragen met een twist.

Kan type narrowing gegarandeerd worden door gewone vergelijkingen (bijvoorbeeld ==/===), en werkt dit altijd?

Antwoord: Nee. In veel gevallen begrijpt TypeScript het type niet uit eenvoudige vergelijkingen, vooral als de vergelijking te "onduidelijk" is of via indirecte variabelen/eigenschappen plaatsvindt. Voor narrowing moet vaak expliciete mechanismen gebruikt worden (typeof, instanceof, discriminante eigenschappen en type guards).

Voorbeeld:

function foo(x: number | string | null) { if (x) { // x: string | number, null is al onmogelijk, maar narrowing naar specifieker type zal er niet zijn } }

Verhaal

In een groot TypeScript-project heeft de conditie user.role == 'admin' het datatype niet genarrowd, en het was nog steeds nodig om controles op eigenschapsexistentie te schrijven. Ontwikkelaars onderschatten de narrowing regels, wat leidde tot fouten "Cannot read property ... of undefined".


Verhaal

In een mobiele applicatie accepteerde de functie ofwel een object of een string. Door een indirecte functie-aanroep die het type veranderde, vond er geen narrowing plaats, en op sommige apparaten was er een crash bij het aanroepen van een methode die niet bij een string hoorde. Testen voor zeldzame gevallen zijn mislukt.


Verhaal

Bij de migratie van code van JavaScript naar TypeScript werden onze type guard functies niet geïmplementeerd, in de veronderstelling dat controles op eigenschappen altijd het type zouden versmallen. Dit resulteerde in complexe objecten met optionele velden die zich niet correct gedroegen, en runtime veroorzaakte onvoorspelbare toegangsfouten naar gegevens.