null und undefined
Manchmal fehlt ein Wert: Ein Held hat kein Haustier, eine Truhe ist leer, eine Suche findet nichts. JavaScript hat zwei Werte für „nichts“. undefined bekommst du von einer fehlenden Eigenschaft oder einem fehlenden Argument. null speichern Programmierer absichtlich, um zu sagen: „Hier ist nichts.“ null hast du im JavaScript-Kurs kennengelernt: querySelector() hat es zurückgegeben, wenn es kein Element gefunden hat, und die nächste Zeile ist mit TypeError: Cannot read properties of null abgestürzt. Dieser Absturz ist einer der häufigsten Fehler in JavaScript-Programmen.
In TypeScript haben null und undefined eigene Typen, und andere Typen schließen sie nicht ein. Eine string-Variable kann kein null enthalten:
let ziel: string = null;main.ts(1,5): error TS2322: Type 'null' is not assignable to type 'string'.Wenn ein Wert fehlen darf, sagst du das mit einer Union: Haustier | null ist „ein Haustier oder nichts“. Und dann sorgt TypeScript dafür, dass du den Wert prüfst, bevor du ihn verwendest:
type Haustier = { name: string; art: string };
type Held = { name: string; haustier: Haustier | null };
function beschreibeHaustier(held: Held): string {
return `${held.name} hat ein Haustier: ${held.haustier.art} namens ${held.haustier.name}`;
}main.ts(5,46): error TS18047: 'held.haustier' is possibly 'null'.
main.ts(5,74): error TS18047: 'held.haustier' is possibly 'null'.„Possibly null“ bedeutet: Wenn die Funktion läuft, kann held.haustier den Wert null haben, und dann würde das Lesen von held.haustier.art mit TypeError: Cannot read properties of null (reading 'art') abstürzen. In JavaScript würdest du es erst merken, wenn das Programm abstürzt, und nur, wenn jemand die Funktion für einen Helden ohne Haustier aufruft. TypeScript sagt es dir, bevor das Programm läuft.
Die Lösung ist eine Prüfung, und sie grenzt den Typ ein, genau wie typeof es getan hat:
type Haustier = { name: string; art: string };
type Held = { name: string; haustier: Haustier | null };
function beschreibeHaustier(held: Held): string {
if (held.haustier === null) {
return `${held.name} hat kein Haustier`;
}
return `${held.name} hat ein Haustier: ${held.haustier.art} namens ${held.haustier.name}`;
}
const kira: Held = { name: "Kira", haustier: { name: "Pip", art: "Eule" } };
const bruno: Held = { name: "Bruno", haustier: null };
console.log(beschreibeHaustier(kira));
console.log(beschreibeHaustier(bruno));Das gibt aus:
Kira hat ein Haustier: Eule namens Pip
Bruno hat kein HaustierUnter dem if mit return ist held.haustier ein Haustier. Du könntest auch andersherum prüfen, mit if (held.haustier !== null) { … }; dann ist held.haustier innerhalb der geschweiften Klammern ein Haustier. Wie du siehst, funktioniert das Eingrenzen auch bei Eigenschaften, nicht nur bei Variablen und Parametern.
haustier: Haustier | null ist nicht dasselbe wie eine optionale Eigenschaft haustier?: Haustier. Hier muss die Eigenschaft immer da sein, und ein Held ohne Haustier hat haustier: null. Eine optionale Eigenschaft darf weggelassen werden, und ihr Typ ist Haustier | undefined: Der Fehler lautet dann is possibly 'undefined' (TS18048), und du prüfst mit !== undefined.
Typischer Fehler: auf das falsche „Nichts“ zu prüfen. if (held.haustier !== undefined) schließt null nicht aus, deshalb meldet TypeScript bei einem Haustier | null weiterhin 'held.haustier' is possibly 'null'. Prüfe auf den Wert, den der Typ enthält.
So schreibst du es:
Anweisungen
- 1
Führe das Programm aus und behebe die Fehler mit einer Prüfung: Wenn
zielden Wertnullhat, gibt die FunktionEs gibt nichts anzugreifenaus und tut sonst nichts. Das Programm gibt dann aus:Der Wolf hat noch 18 Leben Es gibt nichts anzugreifen - 2
Kira hat noch kein neues Ziel gewählt. Erstelle unter den Aufrufen eine Variable (
let)aktuellesZielvom TypMonster | nullmit dem Wertnullund rufegreifAn(aktuellesZiel, 5)auf. - 3
Dann entdeckt Kira einen Goblin. Speichere
{ name: "Goblin", leben: 20 }inaktuellesZielund rufe noch einmalgreifAn(aktuellesZiel, 5)auf. Das Programm gibt dann aus:Der Wolf hat noch 18 Leben Es gibt nichts anzugreifen Es gibt nichts anzugreifen Der Goblin hat noch 15 Leben