How to implement Array-Like class in TypeScript?

38 Views Asked by At

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

2

There are 2 best solutions below

2
Het Modi On

The error you're encountering is because Array constructor expects iterable arguments, and MyArray does not handle the spread of items correctly in the constructor. Here's a corrected version of your code:

class MyArray<T> extends Array<T> {
    constructor(items: T[], data?: any) {
        // If data is provided, spread items inside super call; otherwise, pass empty array
        super(data ? ...items : undefined);

        this.#data = data;
    }

    #data: any;

    public get data() {
        return this.#data;
    }
}

Explanation:

In the constructor, the spread operator ... is used to spread the items array if data is provided. If data is not provided, an empty array is passed to the super call. This ensures that the super call receives an iterable argument as expected. With this corrected code, your example should work as expected:

const myArray = new MyArray([1, 2, 3], {});
console.log(myArray); // Output: MyArray [ 1, 2, 3 ]
console.log(myArray.data); // Output: {}
0
Het Modi On

Let's revise the code to handle the case where data is not provided:

class MyArray<T> extends Array<T> {
    #data: any;

    constructor(items: T[], data?: any) {
        // If data is provided, pass items to super(); otherwise, pass no arguments
        super(...(data ? items : []));

        this.#data = data;
    }

    public get data() {
        return this.#data;
    }
}

In this revised version:

If data is provided, items are spread inside the super() call. If data is not provided, an empty array [] is passed to super().