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:
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"
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:
Nadelen:
Ze gebruiken generics: getProperty<T, K extends keyof T>(), het type key is strikt beperkt tot de sleutels van de structuur.
Voordelen:
Nadelen: