Controllo del tipo di classe in TypeScript


240

In ActionScript è possibile verificare il tipo in fase di esecuzione utilizzando l' operatore is :

var mySprite:Sprite = new Sprite(); 
trace(mySprite is Sprite); // true 
trace(mySprite is DisplayObject);// true 
trace(mySprite is IEventDispatcher); // true

È possibile rilevare se una variabile (estende o) è una determinata classe o interfaccia con TypeScript?

Non ho trovato nulla al riguardo nelle specifiche della lingua. Dovrebbe essere lì quando si lavora con classi / interfacce.

Risposte:


319

4.19.4 L'istanza dell'operatore

L' instanceofoperatore richiede che l'operando di sinistra sia del tipo Any, un tipo di oggetto o un tipo di parametro di tipo e che l'operando di destra sia del tipo Any o di un sottotipo del tipo di interfaccia "Funzione". Il risultato è sempre del tipo primitivo booleano.

Quindi potresti usare

mySprite instanceof Sprite;

Nota che questo operatore è anche in ActionScript ma non dovrebbe più essere usato lì:

L'operatore is, che è nuovo per ActionScript 3.0, consente di verificare se una variabile o espressione è un membro di un determinato tipo di dati. Nelle versioni precedenti di ActionScript, l'operatore instanceof forniva questa funzionalità, ma in ActionScript 3.0 l'operatore instanceof non deve essere utilizzato per verificare l'appartenenza al tipo di dati. L'operatore is deve essere utilizzato al posto dell'operatore instanceof per il controllo manuale del tipo, poiché l'espressione x instanceof y controlla semplicemente la catena prototipo di x per l'esistenza di y (e in ActionScript 3.0, la catena prototipo non fornisce un quadro completo di la gerarchia ereditaria).

TypeScript instanceofcondivide gli stessi problemi. Dato che è una lingua ancora in fase di sviluppo, ti consiglio di dichiarare una proposta di questo tipo.

Guarda anche:


54

TypeScript ha un modo per convalidare il tipo di una variabile in fase di esecuzione. È possibile aggiungere una funzione di convalida che restituisce un predicato di tipo . Quindi puoi chiamare questa funzione all'interno di un'istruzione if ed essere sicuro che tutto il codice all'interno di quel blocco sia sicuro da usare come il tipo che pensi che sia.

Esempio dai documenti TypeScript:

function isFish(pet: Fish | Bird): pet is Fish {
   return (<Fish>pet).swim !== undefined;
}

// Both calls to 'swim' and 'fly' are now okay.
if (isFish(pet)) {
  pet.swim();
}
else {
  pet.fly();
}

Vedi di più su: https://www.typescriptlang.org/docs/handbook/advanced-types.html


29
Questo non è un controllo del tipo di runtime, sta solo controllando se un oggetto ha una certa proprietà. Questo può essere utile per i tipi di unione, quindi funziona per questo caso specifico, ma non è davvero possibile creare un "isThingy" per tutto questo. Anche se sia il pesce che l'uccello potessero nuotare, sei condannato. Sono contento di usare Haxe che ha un controllo dei tipi affidabile, quindi puoi farlo Std.is(pet, Fish), che funziona su tipi, interfacce ecc.
Mark Knol,

4
Ho trovato utile questa risposta, ma penso che potresti modificarla per essere un po 'più precisa. Lo isFishstesso è il predicato che viene creato e il suo corpo non deve essere un predicato a una linea. Il vantaggio di ciò è che il compilatore comprende al momento della compilazione le opportune funzioni possibili, ma il codice all'interno isFishviene eseguito in fase di esecuzione. Si potrebbe anche fare in modo che la guardia contenga instanceofun'istruzione, ad esempio return pet instanceof Fish(supponendo che sia una classe e non un'interfaccia), ma ciò non sarebbe necessario poiché il compilatore capisce instanceofdirettamente.

4
questo è anche chiamato "User Defined Type Guards", vedi basarat.gitbooks.io/typescript/content/docs/types/…
Julian

@MarkKnol in realtà è il controllo di runtime ma porta a dattiloscrivere la capacità di comprendere anche il tipo inferito (significato: puoi fidarti di me questo sarà di tipo X o Y perché lo testerò in fase di runtime).
Flavien Volken

3
Potresti prendere in considerazione l'utilizzo (pet as Fish)poiché lo tslinter si lamenterà (<Fish>pet). Vedi tslint doc
Bryan,

1

È possibile utilizzare l' instanceofoperatore per questo. Da MDN:

L'operatore instanceof verifica se la proprietà prototipo di un costruttore appare in qualsiasi punto della catena prototipo di un oggetto.

Se non sai quali prototipi e catene di prototipi, ti consiglio vivamente di cercarlo. Anche qui c'è un esempio di JS (TS funziona in questo senso simile) che potrebbe chiarire il concetto:

    class Animal {
        name;
    
        constructor(name) {
            this.name = name;
        }
    }
    
    const animal = new Animal('fluffy');
    
    // true because Animal in on the prototype chain of animal
    console.log(animal instanceof Animal); // true
    // Proof that Animal is on the prototype chain
    console.log(Object.getPrototypeOf(animal) === Animal.prototype); // true
    
    // true because Object in on the prototype chain of animal
    console.log(animal instanceof Object); 
    // Proof that Object is on the prototype chain
    console.log(Object.getPrototypeOf(Animal.prototype) === Object.prototype); // true
    
    console.log(animal instanceof Function); // false, Function not on prototype chain
    
    

La catena di prototipi in questo esempio è:

animal> Animal.prototype> Object.prototype

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.