Optionale Eigenschaften in TypeScript werden mit einem Fragezeichen (?) nach dem Eigenschaftsnamen gekennzeichnet. Das bedeutet, dass die Eigenschaft entweder gesetzt oder im Objekt nicht vorhanden sein kann. Dies ist nützlich zur Beschreibung von Strukturen, bei denen nicht alle Felder erforderlich sind.
Beispiel:
interface User { id: number; name?: string; } const u1: User = { id: 1 }; // OK const u2: User = { id: 2, name: 'Ivan' }; // OK
Nuancen:
undefined sein, sondern auch vollständig im Objekt fehlen.if (user.name)) wird undefined nicht von dem Fehlen unterschieden.undefined sein kann, und ohne Überprüfung auf Methoden/Eigenschaften zuzugreifen.Um sich zu schützen:
undefined:if (user.name !== undefined) { console.log(user.name.toUpperCase()); }
console.log(user.name?.toUpperCase());
Wenn ein Objekt das Interface
{ foo?: string }beschreibt, kann die Eigenschaftfooimmer nur ein String oderundefinedsein? Kann man beispielsweise den Wertnullhineinlegen?
Falsche Antwort:
undefined sein, anderes ist nicht erlaubt."Richtige Antwort:
null explizit zugewiesen wird, erlaubt TypeScript das, aber nur, wenn der Typ auf string | null erweitert wird. Standardmäßig nur string oder undefined.interface A { foo?: string } let x: A = { foo: null }; // Fehler!
Geschichte
In einem großen Projekt kamen einige Objekte vom Server ohne bestimmte optionale Felder. Der Programmierer rief direkt Methoden auf diesen Eigenschaften auf (z. B. toLowerCase()), was zu Laufzeitfehlern führte, wenn das Feld fehlte. Um das Problem zu lösen, implementierte das Team strenge Prüfungen und Linter-Regeln für den Zugriff auf optionale Felder.
Geschichte
In logischen Ausdrücken wurde die Existenz der Eigenschaft mit ihrer Wahrheit verwechselt: if (user.email) funktionierte nicht für leere Strings, obwohl die Eigenschaft gesetzt war. Ein Fehler trat auf, weshalb einige Benachrichtigungen nicht an Benutzer gesendet wurden.
Geschichte
Das Team beschloss, den Wert null in eine optionale Eigenschaft zu setzen, in der Annahme, dass dies korrekt sei. TypeScript gab einen Fehler aus, und um dies zu umgehen, musste der Typ auf string | null erweitert werden, was eine Überprüfung der gesamten Geschäftslogik bezüglich dieser Objekte erforderte.