TypeScript"扩展"通用约束

时间:2016-10-05 11:05:49

标签: generics typescript generic-constraints

我在TypeScript中使用extends约束,如下所示:

class Animal {}
class Lion extends Animal {}
class Bear extends Animal { }

class ZooKeeper<T extends Animal> {
    constructor(p: T = new Animal()) {

    }
}

new ZooKeeper(new Animal());

p: T = new Animal()包含错误:

  

Type&#39; Animal&#39;不能分配给&#39; T&#39;。

     

构造函数Animal():Animal

为什么,我该怎么做才能使用Animal代替Animal子类型?

Source

3 个答案:

答案 0 :(得分:2)

将你的动物投射到T上它会起作用。

class ZooKeeper<T extends Animal> {
    constructor(p: T = <T>new Animal()) {

    }
}

根据您自己的评论(对于未来的读者),您也可以这样做:

class ZooKeeper<T extends Animal> {
    constructor(p: T = new Animal() as T) {

    }
}

答案 1 :(得分:1)

你可以从构造函数参数声明中保留赋值,似乎正在为我编译。如果你想留下它,你甚至可以让参数成为可选参数。

更新:正如series0ne所指出的,此解决方案未提供Animal的默认实例,其中未提供一个!{/ p>

class ZooKeeper<T extends Animal> {
    constructor(p?: T) {
    }
}

var zk = new ZooKeeper<Lion>(new Lion());
var zk2 = new ZooKeeper(new Animal());
var zk3 = new ZooKeeper();

将输入ZooKeeper类,您可以访问T的子类特定属性。

答案 2 :(得分:0)

实际上,要完成您想做的事情并不容易。 Animal无法分配给T,因为它们是不同的类型。

考虑示例:

class Lion extends Animal {
  roar() { … }
}
new ZooKeeper<Lion>().animal.roar();

您可以运行它here来查看它在运行时引发异常,因为即使我们将Lion作为T类型传递,我们也会显式创建Animal对象,没有T类型的成员。而且我们无法在构造函数中编写new T(),因为在运行时不存在有关类型的所有信息。

值得一提的是,仅在明确需要时才使用结构<Type>objectobject as Type,因为它不是强制转换,而是类型断言(它告诉编译器'处理' object就像Type一样,即使它不是'?),因此当用作“广播”时,可能会导致难以发现错误。