Ich habe diesen Code geschrieben
interface Foo {
abcdef: number;
}
let x: Foo | string;
if (x instanceof Foo) {
// ...
}
Aber TypeScript hat mir diesen Fehler gegeben:
'Foo' only refers to a type, but is being used as a value here.
Warum passiert das? Ich dachte, das instanceof
könnte überprüfen, ob mein Wert einen bestimmten Typ hat, aber TypeScript scheint dies nicht zu mögen.
javascript
typescript
instanceof
Daniel Rosenwasser
quelle
quelle
Foo | string
.Antworten:
Was ist los
Das Problem ist, dass
instanceof
es sich um ein Konstrukt aus JavaScript handelt und in JavaScriptinstanceof
einen Wert für den Operanden auf der rechten Seite erwartet . Insbesondere wird inx instanceof Foo
JavaScript eine Laufzeitprüfung durchgeführt, um festzustellenFoo.prototype
, ob irgendwo in der Prototypenkette von vorhanden istx
.In TypeScript haben
interface
s jedoch keine Emission. Das bedeutet, dass zur Laufzeit wederFoo
nochFoo.prototype
vorhanden ist, sodass dieser Code definitiv fehlschlägt.TypeScript versucht Ihnen mitzuteilen, dass dies niemals funktionieren könnte.
Foo
ist nur ein Typ, es ist überhaupt kein Wert!"Was kann ich tun anstatt
instanceof
?"Sie können sich Typschutz und benutzerdefinierte Typenschutz ansehen .
"Aber was ist, wenn ich gerade von einem
interface
zu einem gewechselt binclass
?"Sie könnten versucht sein, von einem
interface
zu einem zu wechselnclass
, aber Sie sollten sich darüber im Klaren sein, dass Sie im strukturellen Typensystem von TypeScript (bei dem die Dinge hauptsächlich formbasiert sind ) jedes Objekt erzeugen können, das dieselbe Form wie eine bestimmte Klasse hat:class C { a: number = 10; b: boolean = true; c: string = "hello"; } let x = new C() let y = { a: 10, b: true, c: "hello", } // Works! x = y; y = x;
In diesem Fall haben Sie
x
undy
das haben den gleichen Typ, aber wenn Sie versuchen, einesinstanceof
von beiden zu verwenden, erhalten Sie das andere Ergebnis auf dem anderen. Sieinstanceof
werden also nicht wirklich viel über den Typ erzählen, wenn Sie strukturelle Typen in TypeScript nutzen.quelle
instanceof
mit Klassen gearbeitet wird, nicht mit Schnittstellen. Das musste betont werden.Um zur Laufzeit eine Typprüfung mit einer Schnittstelle durchzuführen , werden Typschutzvorrichtungen verwendet , wenn die zu überprüfenden Schnittstellen unterschiedliche Eigenschaften / Funktionen haben.
Beispiel
let pet = getSmallPet(); if ((pet as Fish).swim) { (pet as Fish).swim(); } else if ((pet as Bird).fly) { (pet as Bird).fly(); }
quelle
Duck
, geben Sie Guard ein, es wirdFish
, aber immer noch keine Laufzeitausnahme, wenn Sie aufrufenswim()
. Schlagen Sie vor, dass Sie eine Ebene der gemeinsamen Schnittstelle erstellen (z. B.Swimmable
) und Ihreswim()
Funktionen dorthin verschieben. Dann sieht Type Guard immer noch gut aus((pet as Swimmable).swim
.'swim' in pet
Bedingung verwenden. Es wird es einzuengen auf eine Teilmenge nach unten , die haben mussswim
definiert (zB:Fish | Mammal
)Daniel Rosenwasser mag Recht und Recht haben, aber ich möchte seine Antwort ändern. Es ist vollständig möglich, die Instanz von x zu überprüfen, siehe das Code-Snippet.
Es ist aber genauso einfach, x = y zuzuweisen. Jetzt wäre x keine Instanz von C, da y nur die Form von C hatte.
class C { a: number = 10; b: boolean = true; c: string = "hello"; } let x = new C() let y = { a: 10, b: true, c: "hello", } console.log('x is C? ' + (x instanceof C)) // return true console.log('y is C? ' + (y instanceof C)) // return false
quelle
Überprüfen Sie, ob Ihre Datei vom richtigen Typ ist. Tags sind in den js-Dateien nicht zulässig, in jsx jedoch
quelle