Hintergrund des Themas:
Der Operator in wurde von TypeScript von JavaScript übernommen und wird häufig verwendet, um die Existenz einer Eigenschaft in einem Objekt zu überprüfen. In TypeScript erhält seine Semantik aufgrund des Typsystems eine zusätzliche Bedeutung — dort ist nicht nur das Vorhandensein eines Wertes wichtig, sondern auch dessen Deklaration auf Typniveau, insbesondere bei optionalen Eigenschaften.
Problem:
Entwickler in TypeScript verwechseln oft die einfache Überprüfung auf undefined mit der Überprüfung des Vorhandenseins der Eigenschaft im Objekt. Ein Fehler kann auftreten, wenn die Eigenschaft vorhanden ist, aber ihr Wert undefined ist oder wenn sie geerbt und nicht direkt im Objekt definiert ist.
Lösung:
Der Operator in überprüft, ob die Eigenschaft tatsächlich in der Prototypenkette des Objekts vorhanden ist, unabhängig von ihrem Wert. Das spielt eine wichtige Rolle bei der Überprüfung optionaler oder berechneter Eigenschaften, was unerwartete Behandlungen von falsy-Werten vermeiden lässt:
Beispielcode:
interface User { id: number; name?: string; } const user1: User = { id: 1 }; const user2: User = { id: 2, name: undefined }; console.log('name' in user1); // false console.log('name' in user2); // true
Hauptmerkmale:
in bestimmt das Vorhandensein einer Eigenschaft im Objekt oder seinem Prototyp, nicht nur die Existenz eines Wertes.Wie unterscheidet sich die Überprüfung auf undefined (obj.prop !== undefined) von der Verwendung von in?
Die Prüfung auf undefined bestimmt nur den Wert, nicht das Vorhandensein der Eigenschaft. Wenn die Eigenschaft vorhanden ist, aber undefined ist, wird das Ergebnis true sein. Wenn die Eigenschaft überhaupt nicht vorhanden ist, ist ihr Wert ebenfalls undefined, aber semantisch handelt es sich um unterschiedliche Fälle.
Beispiel:
const obj: any = { foo: undefined }; console.log('foo' in obj); // true console.log(obj.foo !== undefined); // false console.log('bar' in obj); // false console.log(obj.bar !== undefined); // false
Kann der Operator in das Vorhandensein einer Eigenschaft nur im Objekt selbst überprüfen, während die Prototypenkette ignoriert wird?
Nein, der Standard in überprüft auch die Prototypen. Um nur eigene zu überprüfen, verwenden Sie die Methode hasOwnProperty:
const obj = Object.create({ foo: 123 }); obj.bar = 456; console.log('foo' in obj); // true console.log(obj.hasOwnProperty('foo')); // false
Kann man mit dem in-Operator Typen für union-Typen in TypeScript verfeinern?
Ja, in TypeScript erinnert in an Discriminated Union und ermöglicht es, den Typ auf eine bestimmte Variante zu verfeinern:
type Shape = { kind: 'circle'; radius: number } | { kind: 'square'; size: number }; function getArea(shape: Shape) { if ('radius' in shape) { // Hier ist shape ein Kreis return Math.PI * shape.radius ** 2; } // Hier ist shape ein Quadrat return shape.size ** 2; }
in verwechseln.in für Arrays verwenden (gibt true für numerische Indizes und geerbte Eigenschaften zurück).in für Werte zu verwenden, die keine Objekte sind (zum Beispiel null oder undefined).In einem Projekt mit einem Benutzerarray wurde das optionale Feld mit user.name !== undefined überprüft, was zu falscher Logik für Benutzer führte, deren Eigenschaft ausdrücklich als undefined festgelegt war.
Vorteile:
Nachteile:
Es wurde in verwendet, um das Vorhandensein des optionalen Benutzerfelds unabhängig von seinem Wert genau zu überprüfen, was eine korrekte Unterscheidung zwischen "kein Feld" und "Feld vorhanden, aber Wert nicht gesetzt" ermöglichte.
Vorteile:
Nachteile:
in-Operators, was für Anfänger nicht immer offensichtlich ist.