title: Typescript interface with generic methods
body: <p><strong>Is it possible to have interface in Typescript with generic methods that will allow us to tell that T type will extend some other type?</strong> </p>
  
  <pre><code>interface Abc {
    a: string;
    b: string;
    c: string;
  }
  interface Checkout {
    onComplete&lt;T&gt;(session: T): void
  }
  class StripeCheckout implements Checkout {
    onComplete&lt;T extends Abc&gt;(abc: T) {
      console.log(abc.a);
    }
  }
  </code></pre>
  
  <p>onComplete method is invalid</p>
  
  <pre><code>Property 'onComplete' in type 'StripeCheckout' is not assignable to the same property in base type 'Checkout'.
    Type '&lt;T extends Abc&gt;(session: T) =&gt; void' is not assignable to type '&lt;T&gt;(session: T) =&gt; void'.
      Types of parameters 'session' and 'session' are incompatible.
        Type 'T' is not assignable to type 'Abc'.(2416)
  </code></pre>
  
  <p>Solution #1 (generic interface which will force us to tell types at the class level):</p>
  
  <pre><code>interface Abc {
    a: string;
    b: string;
    c: string;
  }
  interface Checkout&lt;T&gt; {
    onComplete(session: T): void
  }
  class StripeCheckout implements Checkout&lt;Abc&gt; {
    onComplete(session: Abc) {
      console.log(session);
    }
  }
  </code></pre>
  
  <p>Problem is that if I will have more generic methods with different types it will look something like this <code>Abc&lt;T, U, V, Z&gt;</code>. We could fix that with multiple interfaces, however I'd like to tell Typescript about generic method type when I define method in class.</p>
  
  <p>Solution #2 ("generic" with any):</p>
  
  <pre><code>interface Abc {
    a: string;
    b: string;
    c: string;
  }
  interface Checkout {
    onComplete(session: any): void
  }
  class StripeCheckout implements Checkout {
    onComplete(session: Abc) {
      console.log(session);
    }
  }
  </code></pre>
  
  <p>Example usage:</p>
  
  <pre><code>const checkout = new StripeCheckout();
  checkout.onComplete({a: '1', b: '2', c: '3'})
  </code></pre>