I'm developing an Entity Component System and would like to be able to return the concrete type from my get function. Here is how I am currently doing it, which works, but doesn't have any type information:
enum CT { Null, Input, Transform, Physics } // CT = Component Type
class Component {
type: CT;
constructor(type: CT) { this.type = type; }
}
class PhysicsComponent extends Component {
velocity: Vec2;
constructor() {
super(CT.Physics);
this.velocity = new Vec2(0, 0);
}
}
class Entity {
components: Map<CT, Component>;
get = (componentType: CT): any => {
return this.components.get(componentType);
}
}
let physics = entity.get(CT.Physics); // no type-safety since return type is any
I desire type-safety and code-completion, so I'd prefer if I could do something like this in the client-code:
let physics = entity.get<PhysicsComponent>();
But I'm not sure how to set up the library code to allow for something like that. For example, what would components be, and what would my get function look like? Something like..
components: Map<typeof Component, Component>;
get<T extends Component>(): T {
return this.components.get(typeof T) as T;
}
? But that doesn't compile of course.
Also, I'm concerned about performance. Currently the CT enum is just numbers, so everything is very fast (and it needs to be, since querying is the most common operation in the game), and my intuition is that all these typeof calls, casting, and getting type information (which AFAIK is just calling toString on the entire class) are very slow operations, so I'm not even sure if this is a good idea despite the ergonomics, due to performance costs. Any advice?