简体   繁体   中英

Alternative to using enums for specifying types in TypeScript?

In my application I am developing an Entity-Component-System and I need a way of getting objects by their type from a Map. Currently I am doing this:

class Entity {
  components: Map<CT, Component>;

  constructor() {
    this.components = new Map();
  }

  get(componentType: CT): any {
    return this.components.get(componentType);
  }
}

const enum CT {
  Null,
  Health,
  Position,
  // etc..
}

class Component {
  type: CT;

  constructor(type: CT) {
    this.type = type;
  }
}

class HealthComponent extends Component {
  amount: number;
  
  constructor() {
    super(CT.Health);

    this.amount = 0;
  }
}

And then here is some example client code:

let healthComponent = new HealthComponent();
healthComponent.amount = 100;

let entity = new Entity();
entity.components.set(healthComponent.type, healthComponent);

// Later, elsewhere..
let health = entity.get(CT.Health);
console.log(health.amount);

This all works, but it's a bit cumbersome. Every new component I make requires me to make a new entry in the CT enum, and for me to make sure it matches in the new type's constructor. Ideally I'd like to be able to just do something like:

let healthComponent = new HealthComponent();
healthComponent.amount = 100;

let entity = new Entity();
entity.components.set(HealthComponent, healthComponent);

// Later, elsewhere..
let health = entity.get(HealthComponent);
console.log(health.amount);

But I'm not sure if that is possible. Can this be done?

I would just use string as a key and do something like:

class Entity {
  components: Map<string, Component>;

  constructor() {
    this.components = new Map();
  }

  get(componentType: string): any {
    return this.components.get(componentType);
  }
}

And then use the name property of the class like that:

let health = entity.get(Health.name);
console.log(health.amount);

You will have to set target in your tconfig to es6 or esnext file to make it work though. This won't work for interfaces so if you are planning to use them it is also not a good approach.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM