I\'d like to add some functions to the Array class (I\'d rather not have them as functions external to the class since it would ideally be discoverable when typing .>
I think the problem here is that your List
constructor does not expect the same arguments as the Array
constructor.
When built-in methods like map()
create a new array, they construct it using a constructor found in the static Symbol.species class property. This is, by default, the same as the class constructor itself... unless you override it. So List[Symbol.species]
is List
. And List.prototype.map()
will end up calling new List(...)
. I'm pretty sure these methods expect the constructor at [Symbol.species]
to take the same arguments as the Array constructor, namely one of these overloads:
new Array(element0, element1[, ...[, elementN]]); // variadic arguments, one per item in array
new Array(arrayLength); // one numeric argument specifying length
But your List
constructor expects to treat its first (and only) argument items
as an iterable (since it uses spread syntax on it in the call to super(...items)
. When list.map(x=>x*2)
executes it calls something like new List(3)
, and you get an error about 3
not being iterable.
So, what can you do to fix this? By far the easiest way is to make sure that your List
constructor is compatible with the ArrayConstructor type, by having it take the same argument types.
The next easiest thing to do is to override List[Symbol.species]
and return the Array
constructor:
static get [Symbol.species](): ArrayConstructor {
return Array;
}
But that would mean that list.map(x => x*2)
returns an Array
and not a List
.
Assuming you really need your List
constructor to take a single iterable argument instead of the same variadic-or-maybe-a-single-number arguments as Array
, and assuming that you need list.map()
to return a List
, you can override the List[Symbol.species]
property with something more complicated:
static get [Symbol.species](): ArrayConstructor {
return Object.assign(function (...items: any[]) {
return new List(new Array(...items))
}, List) as any;
}
That essentially causes native methods to call new List(new Array(x,y,z))
instead of new List(x,y,z)
.
Okay, hope that makes sense and gives you some direction. Good luck!