I would like to create an Array-Like class and add some properties to it. So far I have this code:
class MyArray<T> extends Array<T> {
constructor(items: T[], data?: any) {
super(...items)
this.#data = data
}
#data: any
public get data() {
return this.#data
}
}
But this code fails with error "Spread syntax requires ...iterable[Symbol.iterator] to be a function":
const myArray = new MyArray([1, 2, 3], {})
myArray.map(item => item+1)
I guess there something wrong with my constructor. Could anyone point me in the right direction please? See TS playground
console.log(myArray)leads to an error: tsplay.dev/WJ3Gvw.map(x => x)it calls the constructor with a single argument3which is the length of the array that is being cloned. This is in line with how the vanillaArrayconstructor works - passing in a single number will initialise an array with this many empty slots. It's probably how cloning works (I'll have to verify but seems to be the case). Which means that the child constructor simply doesn't work the same way..map()is called (and other methods like.slice()) JS would grab the constructor of the array (via@@speciesif it needs to be overridden), creates a new array effectively bynew Ctor(originalArray.length)and then (for.map()at least) it goes over and fills the slots based on the mapping function. You can sort of change the constructor to be more correct for this operation tsplay.dev/w2gZbN However, you lose any additional properties with no easy way to transfer them. Extending seems a bad approach here..map()and get the same object back and what JS has decided to do to ensure it works. Unfortunately the way it's done also means that extending arrays is severely limited. You can very easily add new methods, or override existing ones. But anything other than that, like adding more properties is essentially a no-go as far as I can see. The only solutions are various forms of hacks. Which is a shame.Array, but you pretty much must make the construct signature 100% compatible with whatever the@@specieshappens to be." TS doesn't have a way to constrain construct signatures when you writeclass X extends Y {}so it's pretty much impossible to express. JS is often actively hostile to writing a sound type system and so TS has to make weird tradeoffs. Maybe I should say "TS is insane for trying to represent JS as having strong types."