title: Why is extending {0:T} required to enforce the length of a generic array?
body: <p>I saw this <a href="https://twitter.com/markdalgleish/status/1362702999211008003" rel="nofollow noreferrer">tweet</a> that showed a code snippet on how to enforce the length of a generic array in TypeScript. The code snippet is reproduced below:</p>
  <pre><code>
  type MyArray&lt;T, Length extends number&gt; = Array&lt;T&gt; &amp; { length: Length }
  
  </code></pre>
  <p>The only problem is, it does not work. As can be seen in this <a href="https://www.typescriptlang.org/play?#code/C4TwDgpgBAsiCCAnRBDEAeAKgGigGQgDsBzYACyggA9giATAZykIFcBbAIwkQD4oBeKElQZMfAGRQA3lAA2RUmQBc+BeSgBfAFBb5wKA2AsAZsZVxhadIcQBLErgDMfQQG0ARAHtCEd7nfAAO6eflABZIgQvgC6QA" rel="nofollow noreferrer">playground link</a></p>
  <p>It fails with the following error:</p>
  <pre><code>Type 'string[]' is not assignable to type 'MyArray&lt;string, 3&gt;'.
    Type 'string[]' is not assignable to type '{ length: 3; }'.
      Types of property 'length' are incompatible.
        Type 'number' is not assignable to type '3'.(2322)
  </code></pre>
  <p>Later on in the twitter thread, a <a href="https://twitter.com/_luistak/status/1362899328470298626" rel="nofollow noreferrer">solution</a> was proposed actually worked.</p>
  <p>This is reproduced below:</p>
  <pre><code>type MyArray&lt;T extends any, L extends number&gt; = Array&lt;T&gt; &amp; {
      0: T;
      length: L;
  }
  
  const foo1: MyArray&lt;number, 5&gt; = [1, 2, 3, 4, 5];
  </code></pre>
  <p>And can be seen in this <a href="https://www.typescriptlang.org/play?ssl=6&amp;ssc=50&amp;pln=1&amp;pc=1#code/C4TwDgpgBAsiCCAnRBDEAeAKlCAPYEAdgCYDOUKhIANFADI75FlSECuAtgEYSIB8UALxQkqDJgEAyKAG8AsACgoyqAAYAXFEwBuRQEgANkQDmwABaa6uhQF9FigMYB7QqWBQAZk6cBGTXFE0dHZuXloAVgFhAG0fWgAmWgBmWgAWCIBda0UgA" rel="nofollow noreferrer">playground link</a></p>
  <p>The question is, what difference does <code>{0: T}</code> make? And why is it that extending it makes the code to work?</p>