Vérification du type de classe dans TypeScript


240

Dans ActionScript, il est possible de vérifier le type lors de l'exécution à l'aide de l' opérateur is :

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

Est-il possible de détecter si une variable (étend ou) est une certaine classe ou interface avec TypeScript?

Je n'ai rien trouvé à ce sujet dans les spécifications linguistiques. Il devrait être présent lorsque vous travaillez avec des classes / interfaces.

Réponses:


319

4.19.4 L'opérateur instanceof

L' instanceofopérateur requiert que l'opérande de gauche soit de type Any, un type d'objet ou un type de paramètre de type, et l'opérande de droite soit de type Any ou un sous-type de type d'interface «Fonction». Le résultat est toujours de type primitif booléen.

Vous pouvez donc utiliser

mySprite instanceof Sprite;

Notez que cet opérateur est également en ActionScript mais il ne devrait plus y être utilisé:

L'opérateur is, nouveau pour ActionScript 3.0, vous permet de tester si une variable ou une expression est membre d'un type de données donné. Dans les versions précédentes d'ActionScript, l'opérateur instanceof fournissait cette fonctionnalité, mais dans ActionScript 3.0, l'opérateur instanceof ne devait pas être utilisé pour tester l'appartenance au type de données. L'opérateur is doit être utilisé à la place de l'opérateur instanceof pour la vérification manuelle du type, car l'expression x instanceof y vérifie simplement la chaîne prototype de x pour l'existence de y (et dans ActionScript 3.0, la chaîne prototype ne fournit pas une image complète de la hiérarchie d'héritage).

TypeScript instanceofpartage les mêmes problèmes. Comme il s'agit d'une langue qui est encore en développement, je vous recommande de faire une proposition d'une telle facilité.

Voir également:


54

TypeScript a un moyen de valider le type d'une variable lors de l'exécution. Vous pouvez ajouter une fonction de validation qui renvoie un prédicat de type . Vous pouvez donc appeler cette fonction dans une instruction if, et assurez-vous que tout le code à l'intérieur de ce bloc est sûr à utiliser comme le type que vous pensez qu'il est.

Exemple tiré des documents 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();
}

Voir plus à: https://www.typescriptlang.org/docs/handbook/advanced-types.html


29
Ce n'est pas une vérification de typage à l'exécution, c'est juste une vérification si un objet a une certaine propriété. Cela peut être bien pour les types d'union, donc fonctionne pour ce cas spécifique, mais ce n'est pas vraiment faisable pour créer un "isThingy" pour tout comme ça. Aussi, si les poissons et les oiseaux peuvent nager, vous êtes condamné. Je suis content d'utiliser Haxe qui a une vérification de type fiable pour que vous puissiez le faire Std.is(pet, Fish), qui fonctionne sur les types, les interfaces, etc.
Mark Knol

4
J'ai trouvé cette réponse utile, mais je pense que vous pouvez la modifier pour être un peu plus précise. Le isFishlui-même est le prédicat qui est créé, et son corps n'a pas à être un prédicat à une ligne. L'avantage de ceci est que le compilateur comprend au moment de la compilation les fonctions possibles appropriées, mais votre code à l'intérieur isFishest exécuté au moment de l'exécution. Vous pourriez même demander au garde de contenir une instanceofdéclaration, par exemple return pet instanceof Fish(en supposant que c'est une classe et non une interface), mais cela serait inutile car le compilateur comprend instanceofdirectement.

4
cela s'appelle également "User Defined Type Guards", voir basarat.gitbooks.io/typescript/content/docs/types/…
Julian

@MarkKnol, il s'agit en fait d'une vérification de l'exécution, mais apporte également à la dactylographie la capacité à comprendre le type déduit (ce qui signifie: vous pouvez me faire confiance, ce sera de type X ou Y car je le testerai à l'exécution).
Flavien Volken

3
Vous voudrez peut-être envisager d'utiliser (pet as Fish)car le tslinter se plaindra (<Fish>pet). Voir doc tslint
Bryan

1

Vous pouvez utiliser l' instanceofopérateur pour cela. De MDN:

L'opérateur instanceof teste si la propriété prototype d'un constructeur apparaît n'importe où dans la chaîne de prototype d'un objet.

Si vous ne savez pas ce que sont les prototypes et les chaînes de prototypes, je vous recommande vivement de les rechercher. Voici également un exemple JS (TS fonctionne similaire à cet égard) qui pourrait clarifier le concept:

    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 chaîne prototype dans cet exemple est:

animal> Animal.prototype> Object.prototype

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.