J'ai écrit ce code
interface Foo {
abcdef: number;
}
let x: Foo | string;
if (x instanceof Foo) {
// ...
}
Mais TypeScript m'a donné cette erreur:
'Foo' only refers to a type, but is being used as a value here.
Pourquoi cela arrive-t-il? Je pensais que cela instanceof
pourrait vérifier si ma valeur avait un type donné, mais TypeScript ne semble pas aimer cela.
javascript
typescript
instanceof
Daniel Rosenwasser
la source
la source
Foo | string
.Réponses:
Que se passe-t-il
Le problème est qu'il
instanceof
s'agit d'une construction de JavaScript, et en JavaScript,instanceof
attend une valeur pour l'opérande de droite. Plus précisément, enx instanceof Foo
JavaScript effectuera une vérification d'exécution pour voir s'ilFoo.prototype
existe n'importe où dans la chaîne de prototypes dex
.Cependant, dans TypeScript, les
interface
s n'ont pas d'émission. Cela signifie que niFoo
niFoo.prototype
n'existe au moment de l'exécution, donc ce code échouera définitivement.TypeScript essaie de vous dire que cela ne pourrait jamais fonctionner.
Foo
est juste un type, ce n'est pas du tout une valeur!"Que puis-je faire à la place de
instanceof
?"Vous pouvez examiner les protections de type et les protections de type définies par l'utilisateur .
"Mais que faire si je passais juste d'un
interface
à unclass
?"Vous pourriez être tenté de passer de an
interface
à aclass
, mais vous devez comprendre que dans le système de type structurel de TypeScript (où les choses sont principalement basées sur la forme ), vous pouvez produire n'importe quel objet qui a la même forme qu'une classe donnée: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;
Dans ce cas, vous avez
x
ety
qui ont le même type, mais si vous essayez d'utiliserinstanceof
l'un ou l'autre, vous obtiendrez le résultat opposé sur l'autre. Doncinstanceof
, ne vous en dira pas vraiment beaucoup sur le type si vous tirez parti des types structurels de TypeScript.la source
instanceof
fonctionne avec des classes, pas des interfaces. Pensée qu'il fallait souligner.Pour effectuer la vérification de type lors de l'exécution avec une interface, vous utilisez des protections de type , si les interfaces que vous souhaitez vérifier ont des propriétés / fonctions différentes.
Exemple
let pet = getSmallPet(); if ((pet as Fish).swim) { (pet as Fish).swim(); } else if ((pet as Bird).fly) { (pet as Bird).fly(); }
la source
Duck
, vous tapez guard il devientFish
, mais toujours pas d'exception d'exécution lorsque vous appelezswim()
. Suggérez-vous de créer 1 niveau d'interface commune (par exempleSwimmable
) et de déplacer vosswim()
fonctions là-bas, puis le type guard semble toujours bon avec((pet as Swimmable).swim
.'swim' in pet
condition. Il réduire à un sous - ensemble qui doit avoirswim
défini (ex:Fish | Mammal
)Daniel Rosenwasser a peut-être raison et dandy, mais j'ai envie de modifier sa réponse. Il est tout à fait possible de vérifier l'instance de x, voir l'extrait de code.
Mais il est également facile d'attribuer x = y. Maintenant, x ne serait pas une instance de C car y n'avait que la forme de C.
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
la source
Vérifiez si le fichier ur est dans le bon type. Les balises ne sont pas autorisées dans les fichiers js, mais sont autorisées dans le jsx
la source