'Why is extending {0:T} required to enforce the length of a generic array?

I saw this tweet that showed a code snippet on how to enforce the length of a generic array in TypeScript. The code snippet is reproduced below:


type MyArray<T, Length extends number> = Array<T> & { length: Length }

The only problem is, it does not work. As can be seen in this playground link

It fails with the following error:

Type 'string[]' is not assignable to type 'MyArray<string, 3>'.
  Type 'string[]' is not assignable to type '{ length: 3; }'.
    Types of property 'length' are incompatible.
      Type 'number' is not assignable to type '3'.(2322)

Later on in the twitter thread, a solution was proposed actually worked.

This is reproduced below:

type MyArray<T extends any, L extends number> = Array<T> & {
    0: T;
    length: L;
}

const foo1: MyArray<number, 5> = [1, 2, 3, 4, 5];

And can be seen in this playground link

The question is, what difference does {0: T} make? And why is it that extending it makes the code to work?



Solution 1:[1]

The type you're using, string[], has to be compatible with both the Array and the { length: Length} types. I believe adding the { 0: T } makes the type compatible with the Array.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 David Wheale