5

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

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()包含一个错误:

“动物”类型不能分配给“T”类型。

构造函数动物():动物

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

资源

4

3 回答 3

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) {

    }
}
于 2016-10-05T11:12:57.800 回答
2

您可以只保留构造函数参数声明中的赋值,这对我来说似乎正在正确编译。如果您想保留它,您甚至可以将参数设为可选。

更新:正如series0ne指出的那样,此解决方案不提供未提供的默认实例Animal

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

于 2016-10-05T11:31:21.193 回答
1

实际上,想要做自己想做的事情并不容易。Animal不可分配给,T因为它们是不同的类型。

考虑这个例子:

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

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

还值得一提的是,仅在明确需要时才应使用构造<Type>object或,因为它不是强制类型转换而是类型断言(它告诉编译器'即使不是那样对待'),所以当用作“强制类型转换”时,它可能会导致很难发现错误。object as TypeobjectType

于 2019-07-10T07:42:12.887 回答