我试图在打字稿中实现ECS模式,并创建了ComponentStore
类,其中包含用于后续处理的实体组件。
像这样的组件:
class Health implements IComponent {
name: EComponents = EComponents.health;
}
但是方法setComponent
和getComponents
会引发错误:
错误:(12,11)TS2322:类型'IComponent []'无法分配给类型'T []'。 无法将类型“ IComponent”分配给类型“ T”。
错误:(17,5)TS2322:类型'IComponent []'无法分配给类型'T []'。 无法将类型“ IComponent”分配给类型“ T”。
我这样做的方式类似于Generics in Typescript中的示例,但是它不起作用。
class ComponentStore implements IComponentStore {
private components: Map<EComponents, IComponent[]> = new Map();
setComponent<T extends IComponent>( componentName: EComponents, component: IComponent): void {
const components: T[] = this.components.get(componentName) || [];
this.components.set(componentName, [...components, component ]);
}
getComponents<T extends IComponent>( componentName: EComponents): T[] {
return this.components.get(componentName) || [];
}
}
enum EComponents {
health = 'health',
}
interface IComponent {
name: Ecomponents;
}
我当然可以使用强制转换,但是我认为这不是个好主意。
我希望类型检测对于这些方法能够正常工作
我的目标是设置名称为EComponent
的Map,该名称保留IComponent
之类的一种类型IHealth
的数组,然后将其传输到系统中。
答案 0 :(得分:0)
我不确定您想要什么,但是也许您可以看一下这样的东西:
interface EComponents {
//...
}
interface IComponent {
//...
}
interface IComponentStore<T extends IComponent> {
setComponent(componentName: EComponents, component: T): void;
getComponents(componentName: EComponents): T[];
}
class ComponentStore<T extends IComponent> implements IComponentStore<T> {
private components = new Map<EComponents, T[]>();
setComponent(componentName: EComponents, component: T): void {
const components = this.components.get(componentName) || [];
this.components.set(componentName, [...components, component ]);
}
getComponents(componentName: EComponents): T[] {
return this.components.get(componentName) || [];
}
}
这里的想法是ComponentStore
和IComponentStore
已经为其应处理的IComponent实例获取了通用类型T ...
我假设IComponent
和EComponents
是接口。我为他们提供了一个虚拟的实现。此代码应正确编译。它生成以下JavaScript(定位到ESNext):
"use strict";
class ComponentStore {
constructor() {
this.components = new Map();
}
setComponent(componentName, component) {
const components = this.components.get(componentName) || [];
this.components.set(componentName, [...components, component]);
}
getComponents(componentName) {
return this.components.get(componentName) || [];
}
}
希望它对您有帮助。
编辑:
顺便说一句,IComponentStore
不需要通用。以下代码也适用:
interface EComponents {
//...
}
interface IComponent {
//...
}
interface IComponentStore {
setComponent(componentName: EComponents, component: IComponent): void;
getComponents(componentName: EComponents): IComponent[];
}
class ComponentStore<T extends IComponent> implements IComponentStore {
private components = new Map<EComponents, T[]>();
setComponent(componentName: EComponents, component: T): void {
const components = this.components.get(componentName) || [];
this.components.set(componentName, [...components, component ]);
}
getComponents(componentName: EComponents): T[] {
return this.components.get(componentName) || [];
}
}
它生成相同的JavaScript。
答案 1 :(得分:0)
我更改了IComponent并从中创建通用
interface IComponent<T> {
name: EComponents;
id: string;
}
class ComponentStore implements IComponentStore {
private components: Map<EComponents, IComponent<any>[]> = new Map();
setComponent<T extends IComponent<T>>( componentName: EComponents, component: IComponent<T>): void {
const components: IComponent<T>[] = this.components.get(componentName) || [];
this.components.set(componentName, [...components, component ]);
}
getComponents<T extends IComponent<T>>( componentName: EComponents): IComponent<T>[] {
return this.components.get(componentName) || [];
}
}