ProgrammatieFullstack ontwikkelaar

Hoe werkt de keyof-operator in TypeScript, waarvoor wordt deze gebruikt en hoe beïnvloedt deze het ontwerp van veilige functies en API's?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord.

Achtergrond

TypeScript is vanaf het begin ontwikkeld voor strikte typechecking van objecten en het schrijven van meer voorspelbare code in JavaScript. Een van de hulpmiddelen voor het waarborgen van de veiligheid bij toegang tot de eigenschappen van objecten is de keyof-operator, die is geïntroduceerd in TypeScript 2.1. Deze operator maakt het mogelijk om types te creëren die een set van beschikbare string (en symbol) sleutels in een verklaard objecttype vertegenwoordigen.

Probleem

In puur JavaScript kunnen de eigenschappen van een object op elke string worden opgevraagd, en als er een fout wordt gemaakt, kan dit resulteren in undefined of een fout die pas tijdens runtime wordt ontdekt. Zonder strikte typechecking is het gemakkelijk om een typfout te maken of te vergeten een sleutelstring bij refactoring bij te werken. Bovendien is het vaak nodig om een functie te bouwen die alleen geldige sleutels van een specifiek object- of type accepteert.

Oplossing

De keyof-operator creëert een union-type van alle sleutels van een type. Hiermee kun je de toegestane sleutels beperken, de veiligheid van de API verhogen (bijvoorbeeld voor getter/setter-functies) en generieke hulptypes creëren.

Voorbeeldcode:

type User = { name: string; age: number; active: boolean }; type UserKey = keyof User; // "name" | "age" | "active" function getProp<T, K extends keyof T>(obj: T, key: K): T[K] { return obj[key]; } const user: User = { name: 'Tom', age: 33, active: true }; const age = getProp(user, 'age'); // leeftijd van type number

Belangrijke kenmerken:

  • Maakt het mogelijk om "sleutel"-types te declareren die afhankelijk zijn van de structuur van het object.
  • Maakt get/set-functies voor eigenschappen maximaal typeveilig — typfouten en niet-bestaande sleutels zijn uitgesloten.
  • Werkt ook met symbol-eigenschappen (symbol) vanaf TypeScript 2.7 en hoger.

Lastige vragen.

Wat retourneert keyof voor een array en kan je indices krijgen?

keyof voor een array retourneert de types van de sleutels van het object waarvan de array in JS daadwerkelijk is. Gewoonlijk zijn dit strings van indices en speciale eigenschappen van arrays.

Voorbeeldcode:

type A = keyof number[]; // "length" | "toString" | "pop" | ... | number

Kan keyof sleutels van union-types teruggeven?

Ja, keyof van een union-type retourneert de doorsnede van de sleutels van beide objecten, en niet hun vereniging.

Voorbeeldcode:

type A = {a: string, b: number } type B = {b: number, c: boolean } type C = keyof (A | B); // "b"

Wat gebeurt er als een eigenschap van een object optioneel is? Ondersteunt keyof "?"?

Ja, optionele eigenschappen zijn ook opgenomen in het resulterende type van sleutels, maar dit betekent niet dat de eigenschap noodzakelijkerwijs aanwezig is in het object op runtime.

Voorbeeldcode:

type D = { a: string; b?: number }; type DK = keyof D; // "a" | "b"

Typefouten en anti-patronen

  • Gebruik constante strings voor sleutels in plaats van keyof — verlies van typechecking.
  • Denken dat keyof voor union een vereniging retourneert in plaats van een doorsnede.
  • Verwachten dat keyof alleen expliciet gedeclareerde sleutels, maar geen geërfde, in overweging neemt.

Voorbeeld uit de praktijk

Negatieve case

Ze schrijven een functie getProperty(obj, key) met een sleutel van string-type, aanroepen met een niet-bestaande sleutel — de fout verschijnt pas tijdens runtime.

Voordelen:

  • Generieke code.

Nadelen:

  • Geen controle tijdens de compilatie, mogelijk fouten bij refactoring, kwetsbaarheid voor typfouten.

Positieve case

Ze gebruiken generics: getProperty<T, K extends keyof T>(), het type key is strikt beperkt tot de sleutels van de structuur.

Voordelen:

  • Absolute typeveiligheid, typfouten of fouten in de sleutel zijn onmogelijk.

Nadelen:

  • Code is iets gecompliceerder, generics zijn niet altijd duidelijk voor beginners.