31

I'm using an interface in TypeScript to define a function that is only available on some of the classes that extend the base class. This is a simplified version of the code I have so far:

class Animal {
}

interface IWalkingAnimal {
    walk(): void;
}

class Dog extends Animal implements IWalkingAnimal {
}

class Cat extends Animal implements IWalkingAnimal {
}

class Snake extends Animal {
}

private moveAnimal(animal: Animal) {
    if (animal instanceof Cat || animal instanceof Dog) {
        animal.walk();
    }
}

Now, the trouble is I'll be adding more 'walking' animals so the moveAnimal functional will grow too large to be manageable. What I would like to do is something like this:

private moveAnimal(animal: Animal) {
    if (animal implements IWalkingAnimal ) {
        animal.walk();
    }
}

However the 'implements' check does not work, and I cannot find an equivalent to 'instanceof' when using interfaces. In Java it seems that the use of 'instanceof' would work here, but TypeScript will not allow this.

Does such a thing exist in TypeScript, or is there a better approach here? I am using the TypeScript 1.8.9.

3
  • 1
    why don't you have IWalkingAnimal being a subclass of Animal instead an interface? That way you won't have the problem and it makes sense Commented May 31, 2016 at 10:52
  • 1
    @iberbeu That would work for this simplified example, for flexibility I would like IWalkingAnimal to be an interface so it is not strictly tied to Animal. Thilo's answer below should do the trick. Commented May 31, 2016 at 13:06
  • 1
    Possible duplicate of Interface type check with Typescript Commented Nov 24, 2017 at 8:05

1 Answer 1

37

Unlike classes, interfaces exist only at compile-time, they are not included into the resulting JavaScript, so you cannot do an instanceof check.

You could make IWalkingAnimal a subclass of Animal (and use instanceof), or you could check if the object in question has a walk method:

if (animal['walk']) {}

You can wrap this in a user defined type guard (so that the compiler can narrow the type when used in an if statement, just like with instanceof).

/**
* User Defined Type Guard!
*/
function canWalk(arg: Animal): arg is IWalkingAnimal {
   return (arg as IWalkingAnimal).walk !== undefined;
}


private moveAnimal(animal: Animal) {
    if (canWalk(animal)) {
        animal.walk();  // compiler knows it can walk now
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

I suggest to do (arg as IWalkingAnimal).walk so that if you decide to rename the walk method to something else then the code in the type guard will change as well.
Is this type check bettter then the instanceof subclass option?—OO design wise?

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.