web-dev-qa-db-fra.com

Pourquoi 'instanceof' dans TypeScript me donne-t-il l'erreur "" Foo "ne fait référence qu'à un type, mais est utilisé ici comme valeur."?

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 instanceof pourrait vérifier si ma valeur a un type donné, mais TypeScript ne semble pas aimer ça.

51
Daniel Rosenwasser

Que se passe-t-il

Le problème est que instanceof est une construction de JavaScript et que, en JavaScript, instanceof s'attend à une valeur pour l'opérande de droite. Plus précisément, dans x instanceof Foo JavaScript effectuera une vérification de l'exécution pour voir si Foo.prototype existe dans la chaîne de prototypes de x.

Cependant, dans TypeScript, interfaces n'ont aucune émission. Cela signifie que ni Foo ni Foo.prototype n'existent à l'exécution, donc ce code va définitivement échouer.

TypeScript essaie de vous dire que cela pourrait jamais fonctionner. Foo est juste un type, ce n'est pas une valeur du tout!

"Que puis-je faire au lieu de instanceof?"

Vous pouvez regarder dans gardes de type et gardes de type définis par l'utilisateur .

"Mais si je passais juste d'un interface à un class?"

Vous pourriez être tenté de passer d'un interface à un class, mais vous devez comprendre que dans le système de types structurel de TypeScript (où les éléments sont principalement basé sur la forme), vous pouvez produire tout objet ayant la même forme. en tant que 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 et y qui ont le même type, mais si vous essayez d'utiliser instanceof sur l'un des deux, vous obtiendrez le résultat inverse sur l'autre. Donc, instanceof ne sera pas vraiment ​​vous en dire beaucoup sur le type si vous tirez parti des types structurels dans TypeScript.

62
Daniel Rosenwasser

Daniel Rosenwasser a peut-être raison et dandy mais j'ai envie de faire un amendement à 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'affecter 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
1
Elias Vesterlund