Typescript: Array inheritance in ES6 declaration file (lib.es6.d.ts)

Created on 13 Sep 2016  ·  3Comments  ·  Source: microsoft/TypeScript

ES6 supports Array inheritance, but this is not reflected in the TypeScript declaration file (lib.es6.d.ts).

Array functions like 'filter' and 'slice' return an array of the subclass, so the following should compile in TypeScript:

class MyArray extends Array {
    get size() { return this.length; }
}

var x = new MyArray(10).slice();
x.size;

The functions 'reverse', 'concat', 'slice', 'splice', 'filter' should return with the type 'this'.
The 'map' function returns an instance of the subtype too, but it I don't know how that could be represented in TypeScript, as it would require a generic parameter in the return type, something like:
map<U>(callback: (value: T, index: number, array: this) => U): this<U>

Another issue is the static constructors of the Array class, this should compile too:

var x = MyArray.of(1,2,3);
var y = MyArray.from([1,2,3]);
x.size;
y.size;

There are also some additional complications added by the @@species Symbol, which can be used to change the type signature of the subclass to not use 'this' as the return value for functions like 'filter' and 'slice'. So for the following example, the subclass would work how the return types are defined in the declaration file currently:

class MyArray2 extends Array {
    static get [Symbol.species]() { return Array; }
}

Chrome and Node.js both already implement the array inheritance features shown here.

lib.d.ts Suggestion help wanted

Most helpful comment

the static functions can be solved by making Array a class. the issue is we need to have a way to describe a callable constructor (https://github.com/Microsoft/TypeScript/issues/183), as Array can also be called as a function. unfortunately this proposal has stalled in TC39, but we can do a version of it for ambient declarations. i think this should be tracked separately.

for the rest, adding this in place of T[] should be possible. I believe sort already does this.

All 3 comments

This is going to be difficult, because TypeScript does not currently allow re-slotting of generics on polymorphic this. See #6223 (which this issue could be a considered a dupe of).

The problem becomes if in a subclass you introduce a different generic slot, how does polymorphic this work? For example you create a subclass that only dealt with arrays of arrays, where the generic T was used in this way T[][]. But the generic slot in Array's this would be T[], how do you express that in a way that always works?

There are more examples in the issue mentioned above as well of where polymorphic this breaks down when combined with generics.

The issue with 'map' is indeed the same as the one discussed in "Polymorphic 'this' and Generics", but all the other problematic Array methods could work correctly by simply returning 'this'.

And the Array.from and Array.of methods produce a separate problem, that is also impossible to represent with current TypeScript syntax as far as I know, because the ArrayConstructor interface would have to be able to refer to the 'this' of the Array interface.

the static functions can be solved by making Array a class. the issue is we need to have a way to describe a callable constructor (https://github.com/Microsoft/TypeScript/issues/183), as Array can also be called as a function. unfortunately this proposal has stalled in TC39, but we can do a version of it for ambient declarations. i think this should be tracked separately.

for the rest, adding this in place of T[] should be possible. I believe sort already does this.

Was this page helpful?
0 / 5 - 0 ratings