Search code examples
typescriptpool

How to use an interface mapping to create a new type?


Is something like this possible in Typescript?

const enum ET {
  Collision,
  Dying,
  Collected
}

interface EventMap {
  [ET.Collision]: CollisionEvent;
  [ET.Dying]: DyingEvent;
  [ET.Collected]: CollectedEvent;
}

class GameEvent {
  static grabFromPool(type: ET) {
    let entry = GameEvent.pool[type];

    if (entry.length === 0) {
      return new EventMap[type](); // this line is throwing the error
    } else {
      return entry.pop();
    }
  }

  private static pool: Array<Array<GameEvent>> = [ [], [], [] ];
}

I'm trying to create an object pool. The line I marked is giving the following error:

'EventMap' only refers to a type, but is being used as a value here.ts(2693)

I'm trying to instantiate the corresponding class (example: CollisionEvent) based on the given type parameter (ET).


Solution

  • In your code, EventMap is only a type, with no runtime value. You need a real object:

    const EventMap = {
      [ET.Collision]: CollisionEvent,
      [ET.Dying]: DyingEvent,
      [ET.Collected]: CollectedEvent,
    }
    

    If you need the type:

    type EventMap = typeof EventMap
    // Inferred as this \/
    {
        0: typeof CollisionEvent;
        1: typeof DyingEvent;
        2: typeof CollectedEvent;
    }
    

    Note that in a type expression, CollisionEvent refers to an instance of the class, and typeof CollisionEvent refers to the class and its constructor.