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 instanceofpodría comprobar si mi valor tiene un tipo determinado, pero parece que a TypeScript no le gusta esto.
javascript
typescript
instanceof
Daniel Rosenwasser
fuente
fuente

Foo | string.Respuestas:
Que esta pasando
El problema es que
instanceofes una construcción de JavaScript, y en JavaScript,instanceofespera un valor para el operando del lado derecho. Específicamente, enx instanceof FooJavaScript se realizará una verificación en tiempo de ejecución para ver siFoo.prototypeexiste en algún lugar de la cadena de prototipos dex.Sin embargo, en TypeScript, los
interfaces no tienen emisión. Eso significa que niFooniFoo.prototypeexisten en tiempo de ejecución, por lo que este código definitivamente fallará.TypeScript está tratando de decirle que esto nunca podría funcionar.
Fooes solo un tipo, ¡no es un valor en absoluto!"¿Qué puedo hacer en lugar de
instanceof?"Puede buscar en los protectores de tipos y los protectores de tipos definidos por el usuario .
"¿Pero qué pasa si acabo de cambiar de una
interfacea unaclass?"Es posible que tenga la tentación de cambiar de an
interfacea aclass, pero debe darse cuenta de que en el sistema de tipos estructurales de TypeScript (donde las cosas se basan principalmente en la forma ), puede producir cualquier objeto que tenga la misma forma que una clase determinada: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
xyytiene el mismo tipo, pero si intenta usarinstanceofen cualquiera de los dos, obtendrá el resultado opuesto en el otro. Porinstanceoflo tanto , no le dirá mucho sobre el tipo si está aprovechando los tipos estructurales en TypeScript.fuente
instanceoffunciona con clases, no con interfaces. Pensé que eso necesitaba ser enfatizado.Para realizar la verificación de tipos en tiempo de ejecución con una interfaz, se utilizan protectores de tipos , si las interfaces que desea verificar tienen propiedades / funciones diferentes .
Ejemplo
let pet = getSmallPet(); if ((pet as Fish).swim) { (pet as Fish).swim(); } else if ((pet as Bird).fly) { (pet as Bird).fly(); }fuente
Duck, escribe guard se convierteFish, pero aún no hay excepción de tiempo de ejecución cuando invocasswim(). Sugiero que cree 1 nivel de interfaz común (por ejemploSwimmable) y mueva susswim()funciones allí, luego type guard todavía se ve bien con((pet as Swimmable).swim.'swim' in petcondition. Será limitar la búsqueda a un subconjunto que tiene que haberswimdefinido (por ejemplo:Fish | Mammal)Daniel Rosenwasser puede tener razón y ser elegante, pero me apetece hacer una enmienda a su respuesta. Es completamente posible verificar la instancia de x, vea 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 falsefuente
Compruebe si su archivo es del tipo correcto. Las etiquetas no están permitidas en los archivos js, pero están permitidas en jsx
fuente