【问题标题】:TypeScript - Check if Class implements an InterfaceTypeScript - 检查类是否实现了接口
【发布时间】:2016-09-29 08:11:47
【问题描述】:

我正在使用 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();
    }
}

现在,问题是我要添加更多“行走”的动物,所以 moveAnimal 函数会变得太大而无法管理。我想做的是这样的:

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

但是,“implements”检查不起作用,并且在使用接口时我找不到与“instanceof”等效的选项。在 Java 中,'instanceof' 的使用似乎在这里可以工作,但 TypeScript 不允许这样做。

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

【问题讨论】:

  • 你为什么不让 IWalkingAnimal 作为 Animal 的子类而不是接口?这样你就不会有问题了,这是有道理的
  • @iberbeu 这将适用于这个简化的示例,为了灵活性,我希望 IWalkingAnimal 是一个接口,因此它不严格绑定到 Animal。 Thilo 在下面的回答应该可以解决问题。

标签: typescript


【解决方案1】:

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

您可以将 IWalkingAnimal 设为 Animal 的子类(并使用 instanceof),或者您可以检查相关对象是否具有 walk 方法:

if (animal['walk']) {}

您可以将其包装在 user defined type guard 中(这样编译器可以在 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
    }
}

【讨论】:

  • 我建议使用(arg as IWalkingAnimal).walk,这样如果你决定将 walk 方法重命名为其他名称,那么类型保护中的代码也会随之改变。
猜你喜欢
  • 2010-09-21
  • 1970-01-01
  • 2018-10-19
  • 1970-01-01
  • 2018-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-29
相关资源
最近更新 更多