title: TypeScript cast type using generics and constructor?
body: <p>I have a base class, and sub-classes there of.</p>
  
  <p>Instances of those classes get put in an collection with the type of the base class.</p>
  
  <pre class="lang-js prettyprint-override"><code>class Type extends Object {
      public static ID = 'type';
      public id = 'type';
      constructor() { super(); }
  }
  
  class TypeA extends Type {
      public static ID = 'type-a';
      public id = 'type-a';
      constructor() { super(); }
      public onlyA() { return 'only A has this method'; }
  }
  
  class TypeB extends Type {
      public static ID = 'type-b';
      public id = 'type-b';
      constructor() { super(); }
      public onlyB() { return 'only B has this method'; }
  }
  
  // Discards subclass type information:
  const list: Type[] = [
      new TypeA(),
      new TypeB()
  ];
  
  // Has inferred type: Type
  const list0 = list[0];
  </code></pre>
  
  <p>Now if I know the correct type, I can use <code>as</code> to promote the type:</p>
  
  <pre class="lang-js prettyprint-override"><code>const list0asA = list0 as TypeA;
  list0asA.onlyA();
  </code></pre>
  
  <p>What I'd like to do however is create a generic function that will dynamically check the instance, and return either the promoted type or <code>null</code> if it does not match.</p>
  
  <p>I came up with the following, but it's not quite right:</p>
  
  <pre class="lang-js prettyprint-override"><code>function castOrNull&lt;
      C extends typeof Type
  &gt;(value: Type, Constructor: C): C | null {
      if (value.id !== Constructor.ID) {
          return null;
      }
      return value as C;
  }
  
  const list0castA = castOrNull(list0, TypeA);
  if (list0castA) {
      list0asA.onlyA();
  }
  </code></pre>
  
  <p>The problem is I'm not trying to cast the variable to the constructors type, but the type of an instance of that constructor, so the as and return types are not correct.</p>
  
  <p>Alternately, this does work, but it requires explicitly setting the generic type, meaning specifying the type twice when used, which is less-than-ideal.</p>
  
  <pre><code>function castOrNull&lt;
      T extends Type
  &gt;(value: Type, Constructor: typeof Type): T | null {
      if (value.id !== Constructor.ID) {
          return null;
      }
      return value as T;
  }
  
  const list0upA = castOrNull&lt;TypeA&gt;(list0, TypeA);
  if (list0castA) {
      list0asA.onlyA();
  }
  </code></pre>
  
  <p>Is it possible to create this generic function without specifying the type twice?</p>