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
子类型?
将你的动物投向 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>object
或 object as Type
,因为 它不是强制转换而是类型断言 (它告诉编译器'像 Type
一样对待 object
,即使它不是'),所以当用作“转换”时,它可能会导致难以发现错误。
我在 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
子类型?
将你的动物投向 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>object
或 object as Type
,因为 它不是强制转换而是类型断言 (它告诉编译器'像 Type
一样对待 object
,即使它不是'),所以当用作“转换”时,它可能会导致难以发现错误。