title: Can TypeScript return the subclass if a function has the superclass as its return type?
body: <h1>Problem</h1>
  
  <p>Error: <code>Property 'attach' does not exist on type 'Component'.</code>
  How can I return an arbitrary subclass stored in a custom dictionary type, and use a method that only exists on the subclass if the dictionary type has a return value of the superclass?</p>
  
  <h1>Context</h1>
  
  <p>I have a <code>Component</code> class that has many subclasses.
  My <code>GameActor</code> class can have Components attached to it. An attached component is stored in the <code>ComponentContainer</code> member which is a custom type, and can be any of the subclasses of <code>Component</code>. E.g. <code>MovementComponent</code>, <code>HealthComponent</code>, <code>EventComponent</code>, etc. can all be stored in <code>ComponentContainer</code>.</p>
  
  <p>When I retrieve an attached Component, I get the "Property does not exist" error above when I try and call a method from the retrieved Component. If I open up the browser's dev tools, I can see my log of the returned type looks like it <em>is, in fact, the subclass type</em></p>
  
  <h1>ComponentContainer type definition</h1>
  
  <pre><code>//globals.d.ts
  // ComponentContainer type definition
  // populated data structure will look like:
  // {
  //   "EventComponent": EventComponent,
  //   "MovementComponent": MovementComponent,
  //   "FooComponent": FooComponent
  //   // etc...
  // }
  type ComponentContainer = {
    [componentName: string]: Component;
  }
  </code></pre>
  
  <p>The GameActor has a bunch of methods to add, remove, get, and list the attached components.</p>
  
  <pre><code>
  //GameActor class that can have Components attached to it
  export abstract class GameActor extends GameObject implements IGameActor {
  
    protected components: ComponentContainer;
  
    constructor() {
      this.components = {};
    }
  
    public getComponent(key: string): Component|null {
        return this.components[key];
    }
  }
  
  // Player subclass of GameActor
  export class Player extends GameActor implements IPlayer {
    //Player class code here...
  }
  
  //Component superclass
  export abstract class Component {
    protected typeId: string;
  
    public getTypeId(): string {
      return this.typeId;
    }
  }
  
  //EventComponent subclass
  export class EventComponent extends Component implements IEventComponent {
  
    public attach(event: Event|CustomEvent): void {
      //Attach code here...
    }
  }
  </code></pre>
  
  <p>Now somewhere else in the code I want to do the following:</p>
  
  <pre><code>this.getComponent("EventComponent").attach(PlayerDeathEvent.create(this));
  </code></pre>
  
  <p>at which point I receive the error. If I log out the following code, it appears both are of type <code>EventComponent</code>.</p>
  
  <pre><code>let ec = this.Player.getComponent("EventComponent");
  let t = new EventComponent(); 
  </code></pre>
  
  <p><img src="https://i.imgur.com/BJ4ksA2.png" alt="browser console log"></p>
  
  <p>I expect <code>.attach</code> to not throw an error because the compiler knows the component is of type <code>EventComponent</code>.</p>