Modulelessen (1/2)
Type bewakers
Typevernauwing is een van de belangrijkste concepten in TypeScript. Vaak zijn standaardbeveiligingen zoals typeof of instanceof echter niet voldoende voor complexe aangepaste objecten. Dit is waar Aangepaste Type Guards in beeld komen.
Standaard type bewakers
Laten we beginnen met een samenvatting van hoe TypeScript typen verkleint met behulp van standaard JavaScript-operatoren:
function processInput(val: string | number) {
if (typeof val === 'string') {
// Here 'val' is of type string
console.log(val.toUpperCase());
} else {
// Here 'val' is of type number
console.log(val.toFixed(2));
}
}Aangepaste typebeschermers (operator is)
Om een aangepaste typeguard te definiëren, maken we een functie die een typepredikaat retourneert in de indeling parameterName is Type in plaats van een standaard Booleaans retourtype.
De functie moet een Booleaanse waarde (true of false) retourneren. Als het true retourneert, weet TypeScript dat de doorgegeven parameter van het opgegeven type is.
interface Cat {
name: string;
meow(): void;
}
interface Dog {
name: string;
bark(): void;
}
// This is a custom type guard
function isCat(animal: Cat | Dog): animal is Cat {
return (animal as Cat).meow !== undefined;
}
function makeNoise(pet: Cat | Dog) {
if (isCat(pet)) {
// Here TypeScript knows 'pet' is a Cat
pet.meow();
} else {
// Here TypeScript knows 'pet' is a Dog
pet.bark();
}
}Veiligheid en werpen (as versus Type Guards)
Type casting (bijvoorbeeld val as Cat) dwingt de compiler om de ontwikkelaar te vertrouwen zonder enige echte runtime-verificatie. Als het runtime-object niet aan de verwachtingen voldoet, mislukt de code stil of genereert hij uitzonderingen.
Aangepaste typeguards voeren daarentegen een robuuste en dynamische runtimecontrole uit, waarbij ze de TypeScript-compiler veilig en nauwkeurig informeren over het werkelijke variabeletype:
function processInput(input: unknown) {
// unsafe casting: could crash if input does not have the split method
// const str = input as string;
// console.log(str.split(' '));
// safe guard
if (isString(input)) {
console.log(input.split(' ')); // 100% Safe!
}
}Probeer het zelf
Oefening 1: Stringtype-bescherming
Maak een eenvoudige functie met de naam isString die fungeert als een aangepaste typebeschermer om te verifiëren of een onbekende waarde een tekenreeks is.
Toon hint
Het retourtype van de functie moet val is string zijn, en je moet typeof gebruiken om te controleren of het gelijk is aan 'string'.
Oplossing beschikbaar na 3 pogingen
Oefening 2: Premium gebruikerstypebescherming
Gegeven de typen User en PremiumUser, schrijft u een type guard-functie isPremiumUser(user: User): user is PremiumUser die controleert of de gebruiker de 'premium'-rol heeft.
Toon hint
Definieer de handtekening als functie isPremiumUser(user: User): gebruiker is PremiumUser en vergelijk user.role met 'premium'.
Oplossing beschikbaar na 3 pogingen
Oefening 3: Validatie van aangepaste foutobjecten
Implementeer de isCustomError(err: onbekend): err is de CustomError-functie die verifieert of een onbekende waarde een niet-null CustomError-object is dat de 'code'-sleutel bevat.
Toon hint
Controleer eerst of het type fout 'object' is en niet nul, en gebruik vervolgens de operator 'in' om te controleren op de eigenschap 'code'.
Oplossing beschikbaar na 3 pogingen
Oefening 4: Beheerderstypewacht
Gegeven twee interfaces User (met eigenschapsrol: string) en Admin (uitbreiding van User en met een eigenschap adminToken: string), schrijf een type guard-functie met de naam isAdmin die een gebruiker van het type User accepteert en retourneert dat een type predikaatgebruiker Admin is. De bewaker moet controleren of de rol van de gebruiker gelijk is aan 'admin'.
Toon hint
Definieer de handtekening als functie isAdmin(user: User): gebruiker is Admin en controleer of user.role === 'admin'.
Oplossing beschikbaar na 3 pogingen