Eingrenzen mit typeof
Eine Funktion, die einen string | number bekommt, muss meist jeden Typ anders behandeln. In JavaScript findest du den Typ mit typeof heraus, das du aus dem JavaScript-Kurs kennst: typeof 50 ist "number", und typeof "Silberschwert" ist "string". TypeScript versteht eine solche Prüfung. In diesem Beispiel zahlt die Gilde die Belohnungen für Aufträge aus und behält von jeder Goldbelohnung 5 Gold für sich:
function auszahlung(belohnung: string | number): string {
if (typeof belohnung === "string") {
return `Du bekommst: ${belohnung.toUpperCase()}`;
} else {
return `Du bekommst ${belohnung - 5} Gold (5 für die Gilde)`;
}
}
console.log(auszahlung("Silberschwert"));
console.log(auszahlung(50));Das gibt aus:
Du bekommst: SILBERSCHWERT
Du bekommst 45 Gold (5 für die Gilde)Innerhalb des if weiß TypeScript, dass belohnung ein string ist, deshalb ist toUpperCase() erlaubt. Im else-Zweig bleibt nur number übrig, deshalb ist die Subtraktion erlaubt. Das nennt man Eingrenzen (englisch narrowing): Eine Prüfung macht den Typ innerhalb eines Zweigs enger, von string | number zu nur string oder nur number.
Ohne die Prüfung erlaubt TypeScript die Subtraktion nicht:
function auszahlung(belohnung: string | number): string {
return `Du bekommst ${belohnung - 5} Gold (5 für die Gilde)`;
}main.ts(2,27): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.Diese Meldung kennst du aus der Lektion über Basistypen: Der Wert links von - muss eine Zahl sein.
Eingrenzen funktioniert auch nach return. Wenn der if-Zweig mit return endet, läuft der Rest der Funktion nur für den anderen Typ, und TypeScript weiß das:
function auszahlung(belohnung: string | number): string {
if (typeof belohnung === "string") {
return `Du bekommst: ${belohnung.toUpperCase()}`;
}
return `Du bekommst ${belohnung - 5} Gold (5 für die Gilde)`;
}Unter dem if ist belohnung eine number. Programmierer schreiben Funktionen oft so: zuerst der Sonderfall, der mit return endet, dann der Hauptfall ohne zusätzliche Klammern.
Auch Arrays können Unions enthalten. TypeScript leitet den Typ von [12, "Alter Schlüssel", 40] als (string | number)[] ab: ein Array, dessen Elemente Texte oder Zahlen sind. Wenn du so einen Typ selbst schreibst, vergiss die Klammern nicht. Ohne sie bedeutet number | string[] „eine Zahl oder ein Array von Texten“, und TypeScript lehnt die Zahlen im Array ab:
const beute: number | string[] = [12, "Alter Schlüssel", 40];main.ts(1,35): error TS2322: Type 'number' is not assignable to type 'string'.
main.ts(1,58): error TS2322: Type 'number' is not assignable to type 'string'.Typische Fehler:
typeofliefert den Namen des Typs in Kleinbuchstaben:"string","number","boolean". Fürtypeof belohnung === "String"meldet TypeScripterror TS2367: This comparison appears to be unintentional because the types '"bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined"' and '"String"' have no overlap.Die lange Liste in der Meldung zeigt jeden Text, dentypeofliefern kann, und"String"gehört nicht dazu.- Das Eingrenzen gilt nur innerhalb des Zweigs oder nach einem
ifmitreturn. Unter einemifohnereturnist der Typ wiederstring | number.
So schreibst du es:
Anweisungen
- 1
Führe das Programm aus: TypeScript erlaubt
preis * anzahlnicht, weilpreisein Text sein kann. Füge am Anfang vonformatierePreiseinetypeof-Prüfung hinzu: Wennpreisein Text ist, gibt die Funktion ihn in Großbuchstaben zurück. Das Programm gibt dann aus:50 Gold GRATIS - 2
Erstelle unter den Aufrufen ein Array
preisevom Typ(number | string)[]mit den Werten12,"ausverkauft"und40. - 3
Gehe mit
for...ofdurchpreiseund gib für jeden PreisformatierePreis(preis, 2)aus. Das Programm gibt dann aus:50 Gold GRATIS 24 Gold AUSVERKAUFT 80 Gold