Escribí este código
interface Foo { abcdef: number; } let x: Foo | string; if (x instanceof Foo) { // ... }Pero TypeScript me dio este error:
'Foo' only refers to a type, but is being used as a value here. ¿Por qué está pasando esto? Pensé que instanceof podría verificar si mi valor tiene un tipo dado, pero parece que a TypeScript no le gusta esto.
instanceof funciona con clases, no con interfaces.
El problema es que instanceof es una construcción de JavaScript, y en JavaScript, instanceof espera un valor para el operando del lado derecho. Específicamente, en x instanceof Foo , JavaScript realizará una verificación en tiempo de ejecución para ver si Foo.prototype existe en algún lugar de la cadena de prototipos de x .
Sin embargo, en TypeScript, las interface no emiten. Eso significa que ni Foo ni Foo.prototype existen en tiempo de ejecución, por lo que este código definitivamente fallará.
TypeScript está tratando de decirle que esto nunca podría funcionar. Foo es solo un tipo, ¡no es un valor en absoluto!
instanceof ?"Puede consultar las protecciones de tipo y las protecciones de tipo definidas por el usuario .
interface a una class ?" Es posible que tenga la tentación de cambiar de una interface a una class , pero debe darse cuenta de que en el sistema de tipo estructural de TypeScript (donde las cosas se basan principalmente en la forma ), puede producir cualquier objeto que tenga la misma forma que una clase dada:
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; En este caso, tiene x e y que tienen el mismo tipo, pero si intenta usar instanceof en cualquiera de los dos, obtendrá el resultado opuesto en el otro. Entonces, instanceof realmente no le dirá mucho sobre el tipo si está aprovechando los tipos estructurales en TypeScript.
Para realizar la verificación de tipo en tiempo de ejecución con una interfaz, se utilizan protectores de tipo , si las interfaces que desea verificar tienen diferentes propiedades/funciones.
Ejemplo
let pet = getSmallPet(); if ((pet as Fish).swim) { (pet as Fish).swim(); } else if ((pet as Bird).fly) { (pet as Bird).fly(); }Daniel Rosenwasser podría tener razón y ser elegante, pero tengo ganas de modificar su respuesta. Es completamente posible verificar la instancia de x, consulte el fragmento de código.
Pero es igualmente fácil asignar x = y. Ahora x no sería una instancia de C ya que y solo tenía la forma 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