Diese Frage ist die direkte Analogie zur Überprüfung des Klassentyps mit TypeScript
Ich muss zur Laufzeit herausfinden, ob eine Variable vom Typ eine Schnittstelle implementiert. Hier ist mein Code:
interface A{
member:string;
}
var a:any={member:"foobar"};
if(a instanceof A) alert(a.member);
Wenn Sie diesen Code auf dem Typoskript-Spielplatz eingeben, wird die letzte Zeile als Fehler markiert: "Der Name A ist im aktuellen Bereich nicht vorhanden." Das stimmt aber nicht, der Name existiert im aktuellen Bereich. Ich kann die Variablendeklaration sogar var a:A={member:"foobar"};
ohne Beschwerden des Editors ändern . Nachdem ich im Internet surft und die andere Frage zu SO gefunden habe, habe ich die Benutzeroberfläche in eine Klasse geändert, kann dann aber keine Objektliterale zum Erstellen von Instanzen verwenden.
Ich fragte mich, wie der Typ A so verschwinden könnte, aber ein Blick auf das generierte Javascript erklärt das Problem:
var a = {
member: "foobar"
};
if(a instanceof A) {
alert(a.member);
}
Es gibt keine Darstellung von A als Schnittstelle, daher sind keine Laufzeit-Typprüfungen möglich.
Ich verstehe, dass Javascript als dynamische Sprache kein Konzept von Schnittstellen hat. Gibt es eine Möglichkeit, eine Typprüfung für Schnittstellen durchzuführen?
Die automatische Vervollständigung des Typoskript-Spielplatzes zeigt, dass Typoskript sogar eine Methode bietet implements
. Wie kann ich es benutzen?
Antworten:
Sie können ohne das
instanceof
Schlüsselwort erreichen, was Sie wollen, da Sie jetzt benutzerdefinierte Typwächter schreiben können:Viele Mitglieder
Wenn Sie viele Mitglieder überprüfen müssen, um festzustellen, ob ein Objekt Ihrem Typ entspricht, können Sie stattdessen einen Diskriminator hinzufügen. Das folgende Beispiel ist das grundlegendste und erfordert, dass Sie Ihre eigenen Diskriminatoren verwalten. Sie müssen sich eingehender mit den Mustern befassen, um sicherzustellen, dass Sie doppelte Diskriminatoren vermeiden.
quelle
isInstanceOfA(instantiatedB)
true zurückgeben, aberisInstanceOfB(instantiatedA)
false. Müsste der Diskriminator von B nicht "I-AM-A" sein, damit letzteres eintritt?In TypeScript 1.6 erledigt der benutzerdefinierte Typschutz die Aufgabe.
Und genau wie Joe Yang erwähnt hat: Seit TypeScript 2.0 können Sie sogar den Vorteil von Tagged Union Type nutzen.
Und es funktioniert auch mit
switch
.quelle
object is type
undobject instanceof class
besteht darin, dass die Eingabe von TypeScript strukturell ist und sich nur um die "Form" kümmert, anstatt darum, woher ein Objekt die Form hat: ein einfaches Objekt oder eine Instanz einer Klasse, es spielt keine Rolle.type
Eigenschaft erstellt wurden. In diesem Fall funktioniert es. Dieses Beispiel zeigt diese Tatsache nicht.Typoskript 2.0 führt Tagged Union ein
Typescript 2.0-Funktionen
quelle
Wie wäre es mit benutzerdefinierten Typwächtern? https://www.typescriptlang.org/docs/handbook/advanced-types.html
quelle
(pet as Fish).swim !== undefined;
funktioniert.Es ist jetzt möglich, dass ich gerade eine erweiterte Version des
TypeScript
Compilers veröffentlicht habe, die vollständige Reflexionsfunktionen bietet. Sie können Klassen aus ihren Metadatenobjekten instanziieren, Metadaten von Klassenkonstruktoren abrufen und Schnittstellen / Klassen zur Laufzeit überprüfen. Sie können es hier überprüfenAnwendungsbeispiel:
Erstellen Sie in einer Ihrer Typoskriptdateien eine Schnittstelle und eine Klasse, die sie wie folgt implementiert:
Lassen Sie uns nun einige der Liste der implementierten Schnittstellen drucken.
Kompilieren Sie mit Reflect-ts und starten Sie es:
Siehe Reflection.d.ts für
Interface
Details zum Metatyp.UPDATE: Ein ausführliches Beispiel finden Sie hier
quelle
implements
wollte aber dein Engagement anerkennen und wollte nicht gemein sein :-)Wie oben, wo benutzerdefinierte Schutzvorrichtungen verwendet wurden, diesmal jedoch mit einem Pfeilfunktionsprädikat
quelle
Hier ist eine weitere Option: Das Modul ts-interface-builder bietet ein Build-Time-Tool, das eine TypeScript-Schnittstelle in einen Laufzeitdeskriptor konvertiert, und ts-interface-checker kann prüfen, ob ein Objekt diese Anforderungen erfüllt.
Für das Beispiel von OP:
Sie würden zuerst ausführen,
ts-interface-builder
wodurch eine neue übersichtliche Datei mit einem Deskriptor erstellt wirdfoo-ti.ts
, den Sie beispielsweise folgendermaßen verwenden können:Sie können eine Einzeiler-Typschutzfunktion erstellen:
quelle
Ich möchte darauf hinweisen, dass TypeScript keinen direkten Mechanismus zum dynamischen Testen bietet, ob ein Objekt eine bestimmte Schnittstelle implementiert.
Stattdessen kann TypeScript-Code mithilfe der JavaScript-Technik prüfen, ob auf dem Objekt eine geeignete Gruppe von Elementen vorhanden ist. Beispielsweise:
quelle
for (element in obj) {}
), um zu überprüfen, ob die beiden Objekte ähnliche Elemente ähnlicher Typen aufweisen.TypeGuards
quelle
Basierend auf der Antwort von Fenton ist hier meine Implementierung einer Funktion, um zu überprüfen, ob eine gegebene
object
die Schlüsselinterface
hat, die sie ganz oder teilweise hat.Abhängig von Ihrem Anwendungsfall müssen Sie möglicherweise auch die Typen der einzelnen Eigenschaften der Schnittstelle überprüfen. Der folgende Code macht das nicht.
Anwendungsbeispiel:
quelle
quelle
Da der Typ zur Laufzeit unbekannt ist, habe ich folgenden Code geschrieben, um das unbekannte Objekt nicht mit einem Typ, sondern mit einem Objekt bekannten Typs zu vergleichen:
Hier ist der (schnittstellenunabhängige) Code, den ich für den Tiefenvergleich verwende:
Unten ist ein Beispiel, wie ich es benutze.
In diesem Beispiel erwarte ich, dass JSON ein Array von Tupeln enthält, von denen das zweite Element eine Instanz einer aufgerufenen Schnittstelle ist
User
(die zwei optionale Elemente enthält).Durch die Typprüfung von TypeScript wird sichergestellt, dass mein Beispielobjekt korrekt ist. Anschließend überprüft die Funktion assertTypeT, ob das unbekannte (von JSON geladene) Objekt mit dem Beispielobjekt übereinstimmt.
Sie können eine solche Prüfung bei der Implementierung eines benutzerdefinierten Typschutzes aufrufen.
quelle
Sie können einen TypeScript-Typ zur Laufzeit mit ts-validate-type validieren (erfordert jedoch ein Babel-Plugin):
quelle