524

In ActionScript, it is possible to check the type at run-time using the is operator:

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

Is it possible to detect if a variable (extends or) is a certain class or interface with TypeScript?

I couldn't find anything about it in the language specs. It should be there when working with classes/interfaces.

2
  • Is this question about TypeScript? Or ActionScript? These two are very significantly different languages with very different syntax and capabilities. Pick one over the other. Don't ask about both in one place. Commented Apr 29 at 18:42
  • If you look at the date, it is a historical question. At the time flash (and actionscript) was sunsetted. "Dont ask about both in one place" is very senseless, the comparison is very important. Commented May 1 at 5:34

5 Answers 5

635

4.19.4 The instanceof operator

The instanceof operator requires the left operand to be of type Any, an object type, or a type parameter type, and the right operand to be of type Any or a subtype of the 'Function' interface type. The result is always of the Boolean primitive type.

So you could use

mySprite instanceof Sprite;

Note that this operator is also in ActionScript but it shouldn't be used there anymore:

The is operator, which is new for ActionScript 3.0, allows you to test whether a variable or expression is a member of a given data type. In previous versions of ActionScript, the instanceof operator provided this functionality, but in ActionScript 3.0 the instanceof operator should not be used to test for data type membership. The is operator should be used instead of the instanceof operator for manual type checking, because the expression x instanceof y merely checks the prototype chain of x for the existence of y (and in ActionScript 3.0, the prototype chain does not provide a complete picture of the inheritance hierarchy).

TypeScript's instanceof shares the same problems. As it is a language which is still in its development I recommend you to state a proposal of such facility.

See also:

Sign up to request clarification or add additional context in comments.

Comments

159

TypeScript have a way of validating the type of a variable in runtime. You can add a validating function that returns a type predicate. So you can call this function inside an if statement, and be sure that all the code inside that block is safe to use as the type you think it is.

Example from the TypeScript docs:

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();
}

See more at: https://www.typescriptlang.org/docs/handbook/advanced-types.html

6 Comments

This is not runtime typechecking, it's just checking if a object has a certain property. This may be nice for union types so works for this specific case, but its not really doable to create a "isThingy" for everything like this. Also if both fish and bird could swim you're doomed. I'm glad I'm using Haxe which has a reliable type checking so you can do Std.is(pet, Fish), which works on types, interfaces etc.
I found this answer helpful, but I think you could tweak it to be a little more precise. The isFish itself is the predicate that is created, and its body doesn't have to be a one-liner predicate. The advantage of this is that the compiler understands at compile time the appropriate possible functions, but your code inside isFish is executed at runtime. You could even have the guard contain an instanceof statement, e.g. return pet instanceof Fish (assuming it's a class and not an interface), but this would be unnecessary since the compiler understands instanceof directly.
this is also called "User Defined Type Guards", see basarat.gitbooks.io/typescript/content/docs/types/…
@MarkKnol it actually is runtime checking but brings as to typescript the ability to understand the inferred type as well (meaning: you can trust me this will be type X or Y because I will test it at runtime).
You may want to consider using (pet as Fish) since the tslinter will complain about (<Fish>pet). See tslint doc
|
29

You can use the instanceof operator for this. From MDN:

The instanceof operator tests whether the prototype property of a constructor appears anywhere in the prototype chain of an object.

If you don't know what prototypes and prototype chains are I highly recommend looking it up. Also here is a JS (TS works similar in this respect) example which might clarify the 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
    
    

The prototype chain in this example is:

animal > Animal.prototype > Object.prototype

Comments

20

You have two types of checks

by ex, the isString check can be performed like this:

function isString(value) {
    return typeof value === 'string' || value instanceof String;
}

1 Comment

If you are going to use a separate function for codified type checks, it would be best to also tell the compiler about this being a type predicate so that calling the function subsequently narrows the type of the argument: function isString(value): value is string { return typeof value === 'string' || value instanceof String; } const x: any = "im a string!"; if (isString(x)) console.log(x.toUpperCase()); Note that the return type is value is string.
7

Although late and already some good answers exists. The proposed solution from @Gilad has the flaw if the assigned content swim exists as Type but the Value is set to undefined. A more robust check would be:

export const isFish= (pet: Fish | Bird): pet is Fish =>
   'swim' in pet;

This solution wouldn't be dependent on the value of swim!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.