title: TypeScript this in interface should reference itself and children, not only itself
body: <p>There is the example:</p>
  <pre><code>interface A {
      method: (itself: this) =&gt; string;
  }
  
  interface B extends A {
      additionalProperty: boolean;
  }
  
  type Extend&lt;T extends A&gt; = A &amp; { extension: number };
  
  type ExtendedA = Extend&lt;A&gt;
  
  type ExtendedB = Extend&lt;B&gt;
  </code></pre>
  <p><a href="https://www.typescriptlang.org/play?ts=4.6.2&amp;ssl=13&amp;ssc=27&amp;pln=1&amp;pc=1#code/JYOwLgpgTgZghgYwgAgILIN4CgCQBbCMACwHsATALmQApgwBnCAGxiuOHoEpkBeAPmT0wUUAHMA3FgC+WLKEixEKAELIIAD0ggy9NJlxwyZOsBIg4TAApQSAB2hgAnlQBGJEkwhwQkmVif2yACimhDaADwAKmqh2rqoAjx6AGSYMVr0piBUIACueC7QyFKS-o6BIVpkEGToSZVhZOEJsgEoDdo1qvWxTcp8QA" rel="noreferrer">The sandbox</a>.</p>
  <p>When I try to extend <code>B</code> TypeScript writes:</p>
  <blockquote>
  <p>Type 'B' does not satisfy the constraint 'A'.
  Types of property 'method' are incompatible.
  Type '(itself: B) =&gt; string' is not assignable to type '(itself: A) =&gt; string'.
  Types of parameters 'itself' and 'itself' are incompatible.
  Property 'additionalProperty' is missing in type 'A' but required in type 'B'.(2344)
  input.tsx(6, 2): 'additionalProperty' is declared here.</p>
  </blockquote>
  <p>But <code>B</code> extends <code>A</code>. They should be compatible.</p>
  <p><strong>UPDATE #1:</strong></p>
  <p>I can't explain this, but <a href="https://www.typescriptlang.org/play?ts=4.6.2#code/MYGwhgzhAECC0G8BQBIAtgUwC4AsD2AJgBQCWWEGIAZgFzS4kQCUiqKATtgK7sB20AciwYIWAQG5UAXyQzQkGACFoGAB7DeBGPGQowBAmRJ5eYEAAV2eAA4Z2WAJ7QAvPXZcMkmUke3oAUXUMTQAeABUVIM1tAD4XaAiAMkRIjQhjXjpeLjQAIztoKUkfBz9AjQIMAnhXcuCCENgYpBKyqMqCZVr2kMUYoA" rel="noreferrer">it seems that if I replace interfaces by classes</a> typing works perfect.</p>
  <p><strong>UPDATE #2:</strong></p>
  <p>Well, it works only with class methods, but it doesn't work, for example, arrow functions. Still strange.</p>
  <p><strong>UPDATE #3</strong></p>
  <p>If the interface is defined in the following way it doesn't work:</p>
  <pre><code>interface A {
      method: (itself: this) =&gt; string;
  }
  </code></pre>
  <p>But if it's defined in the following way it does work:</p>
  <pre><code>interface A {
      method(itself: this): string;
  }
  </code></pre>
  <p>It has no sense at all. But looking for the reason of this behavior I found <a href="https://stackoverflow.com/a/70277549">this excellent answer</a>. It gave me a clue to reasons of this difference.</p>
  <p>There was mentioned the TypeScript option <a href="https://github.com/microsoft/TypeScript-Website/blob/v2/packages//tsconfig-reference/copy/en/options/strictFunctionTypes.md" rel="noreferrer"><code>strictFunctionTypes</code></a>.</p>
  <blockquote>
  <p>When enabled, this flag causes functions parameters to be checked more correctly.</p>
  </blockquote>
  <blockquote>
  <p>During development of this feature, we discovered a large number of inherently unsafe class hierarchies, including some in the DOM. Because of this, the setting only applies to functions written in function syntax, not to those in method syntax</p>
  </blockquote>
  <p>It explains the reason of that strange difference in behavior. I can just turn off this option, but it feels like a workaround.</p>
  <p>I still need another solution.</p>
  <p><strong>UPDATE #4</strong></p>
  <p>I assume this error is designated to prevent such unsafe assignments:</p>
  <pre><code>const a: A = {
      method(b: B) {
          return `${b.toString()} / ${b.additionalProperty}`;
      }
  }
  </code></pre>
  <p>But such type of errors are not specific for my case.</p>
  <p><strong>UPDATE #5</strong></p>
  <p>I've found another workaround</p>
  <pre><code>type Method&lt;T extends (...args: any) =&gt; any&gt; = {
      f(...args: Parameters&lt;T&gt;): ReturnType&lt;T&gt;;
  }['f'];
  </code></pre>
  <pre><code>interface A {
      method: Method&lt;(itself: this) =&gt; string&gt;;
  }
  
  interface B extends A {
      additionalProperty: boolean;
  }
  
  type Extend&lt;T extends A&gt; = T &amp; { extension: number };
  
  type ExtendedA = Extend&lt;A&gt;
  
  type ExtendedB = Extend&lt;B&gt;
  </code></pre>
  <p><a href="https://www.typescriptlang.org/play?ts=4.6.2#code/C4TwDgpgBAshwAsD2ATAPAFShAHsCAdigM5QAUAdFQIYBOA5sQFxTUEgCUUAvAHyvt+3KAG8AUAEgAZpRoNmUAAp1qAW3gRaxTLw4sASvACutAhnAQdAbjEBfANoByKY4C6NsQEsC+WlOoAxtAAgqKS6oioLHCR6GSewMQQADZSLIiexFx8UMTAtN70vDa2Yl4+mv5BUABC2HiEJFCh4hLUKCgJnkgE1MmKtEiQtKAsAEZISMkQbCVloJBQAKINRJj1+ESkwUJQWABkohuExN0ELARGqmOaULYeC9ArmygQKKHCz41oO-MWy6tXig6p9AWgarwgA" rel="noreferrer">Check it yourself</a>. It's better than disabling of <code>strictFunctionTypes</code>, but it's still workaround.</p>