TypeScript - 检查Class是否实现了接口

Mar*_*ney 20 typescript

我在Typescript中使用一个接口来定义一个仅在扩展基类的某些类上可用的函数.这是我到目前为止的代码的简化版本:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,问题是我将添加更多"行走"动物,因此moveAnimal功能将变得太大而无法管理.我想做的是这样的事情:

private moveAnimal(animal: Animal) {
    if (animal implements IWalkingAnimal ) {
        animal.walk();
    }
}
Run Code Online (Sandbox Code Playgroud)

但是'implements'检查不起作用,我在使用接口时找不到'instanceof'的等价物.在Java中,似乎使用'instanceof'可以在这里工作,但TypeScript不允许这样做.

TypeScript中是否存在这样的东西,或者这里有更好的方法吗?我使用的是TypeScript 1.8.9.

Thi*_*ilo 28

与类不同,接口仅在编译时存在,它们不包含在生成的Javascript中,因此您无法进行instanceof检查.

您可以创建IWalkingAnimalAnimal的子类(并使用instanceof),或者您可以检查相关对象是否有walk方法:

if (animal['walk']) {}
Run Code Online (Sandbox Code Playgroud)

您可以将它包装在用户定义的类型保护中(这样编译器可以在if语句中使用时缩小类型,就像使用一样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
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我建议做`(arg as IWalkingAnimal).walk`,这样如果你决定将walk方法重命名为其他东西,那么类型后卫中的代码也会改变. (4认同)