简体   繁体   English

如何在 Typescript 中将抽象 class 类型作为通用参数传递?

[英]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)

上述代码块中描述的错误在 Visual Studio Code 中发生的屏幕截图

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.

相关问题 传递类作为泛型参数打字稿 - Pass class as generic parameter Typescript TypeScript:将通用类型作为参数传递给通用类 - TypeScript: pass generic type as parameter in generic class 在TypeScript条件类型中,如何测试函数/通用参数的存在? - In TypeScript conditional types, how can I test for the presence of a function/generic parameter? Typescript:将泛型类传递给函数参数 - Typescript: Pass generic class to function parameter 在Typescript中,为什么我的通用抽象类在尝试实现它时没有找到类型参数? - In Typescript, why isn't my generic abstract class finding the type parameter when I attempt to implement it? 如何在TypeScript中将eta简化的泛型函数作为参数传递? - How can I pass an eta-reduced generic function as a parameter in TypeScript? 如何使 TypeScript 通用 class 仅限于对象数组的类型? - How can I make a TypeScript generic class to be constrained only to types that are an array of objects? 如何使用 Typescript 将属性作为参数传递? - How can I pass an attribute as a parameter with Typescript? 如何在 TypeScript 中使用泛型参数扩展泛型参数? - How can I extend a genric parameter with a generic parameter in TypeScript? 如何在 TypeScript 中创建内联抽象 class? - How can I create an inline abstract class in TypeScript?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM