[英]How can I pass abstract class types as a generic parameter in Typescript?
I'm trying to figure out how I can pass abstract class types as a parameter to a generic method in TypeScript.我试图弄清楚如何将抽象 class 类型作为参数传递给 TypeScript 中的通用方法。
I'm working on an Entity-Component system in Typescript.我正在研究 Typescript 中的实体组件系统。 This means I have entities, which are containers of components, and I can fetch any arbitrary component from them.
这意味着我有实体,它们是组件的容器,我可以从中获取任意组件。 Here's a minimal example:
这是一个最小的例子:
abstract class Component { }
class PlayerController extends Component { }
class MonsterController extends Component { }
class LaserGun extends Component { }
class Collider extends Component { }
class Movement extends Component { } // etc, you get the idea
class Entity {
public components: Component[] = [];
public fetch<T extends Component>(componentType: { new(): T }): T | undefined {
return this.components.find(c => c instanceof componentType) as T;
}
}
Now I can fetch individual component types like this:现在我可以像这样获取单个组件类型:
const entity = new Entity();
entity.components.push(new PlayerController());
entity.components.push(new Movement());
entity.components.push(new LaserGun());
const playerController = entity.fetch(PlayerController);
// ^ this variable controller is typed PlayerController,
// so I can use PlayerController-specific features.
However, I want to upgrade this structure by being able to request abstract types.但是,我想通过能够请求抽象类型来升级这个结构。 For example, I could have other Weapons beside LaserGun, and just request any Weapon at all that's attached to the class without caring which kind of weapon it is, like this:
例如,我可以在 LaserGun 之外拥有其他武器,并且只需请求任何附加到 class 的武器,而不关心它是哪种武器,如下所示:
abstract class Weapon extends Component {
public abstract attack(): void;
}
class LaserGun extends Weapon {
public attack(): void { /* pew pew */ }
}
class Sword extends Weapon {
public attack(): void { /* swish swish */ }
}
I can't actually fetch this abstract class though, because abstract classes don't have constructors, and TypeScript doesn't let me pass them as a parameter to the above method:我实际上无法获取这个抽象 class ,因为抽象类没有构造函数,并且 TypeScript 不允许我将它们作为参数传递给上述方法:
const weapon = entity.fetch(Weapon);
// ~~~~~~
// Argument of type 'typeof Weapon' is not assignable to parameter of type 'new () => Weapon'.
// Cannot assign an abstract constructor type to a non-abstract constructor type.ts(2345)
How can I update my fetch()
method to allow me to pass any class type that extends Component, including abstract classes?如何更新我的
fetch()
方法以允许我传递任何扩展 Component 的 class 类型,包括抽象类?
For now my workaround is to simply make Weapon a non-abstract class, but I'd like to know how to do this in a way that lets me use abstract classes.现在我的解决方法是简单地使武器成为非抽象 class,但我想知道如何以让我使用抽象类的方式做到这一点。
You can use abstract construct signatures for that ( playground ):您可以为此使用抽象构造签名( 操场):
class Entity {
public components: Component[] = [];
public fetch<T extends Component>(componentType: abstract new() => T): T | undefined {
return this.components.find(c => c instanceof componentType) as T;
}
}
// no errors
const weapon = entity.fetch(Weapon);
const sword = entity.fetch(Sword);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.