TypeScript "extends" 泛型约束

TypeScript "extends" generic constraint

我在 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 'Animal' is not assignable to type 'T'.

constructor Animal(): Animal

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

Source

将你的动物投向 T,它会起作用。

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

    }
}

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

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

    }
}

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

更新: 正如 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 class,您可以访问 T 的子 class 特定属性。

其实,想做自己想做的事,真的不容易。 Animal 不能分配给 T 因为它们是不同的类型。

考虑示例:

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

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

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