REST Parameters in class inheritance

Topics: General
May 9, 2014 at 10:11 AM
I'm using rest parameters in my constructor function for both the base class and the derived class. However because TypeScript has converted the REST parameter to an array in the dervied class, when super is called it passes an array over to the base class and so the base call constructor is called with an array rather than REST parameters. See playground example below where I want the behavior of the print function to be ['red', 'green', 'blue'] rather than [['red', 'green', 'blue']].
class A {
    private list: Array<any>;
    constructor(...list: Array<any>) { 
        this.list = list;
    }
    
    public print() {
        console.log(this.list);
    }
}

class B extends A {
    constructor(public name: string, ...list: Array<any>) { 
        super(list); 
    }
}

var b: B = new B('bob', 'red', 'green', 'blue');

b.print();
May 9, 2014 at 1:10 PM
That's how it's supposed to work. What's missing is spreading arrays to parameters: http://tc39wiki.calculist.org/es6/spread/

TypeScript is about supporting ES6 patterns today, not creating something else. ;)
May 9, 2014 at 2:04 PM
Yeah I know. Just wanted to see if there was any implementation change I could make without changing the design to accept an array instead :)
May 9, 2014 at 2:59 PM
I think you'll just have to do something like this for now:
class A {
    private list: Array<any>;
    
    constructor(...list: Array<any>) {
        if (list.length == 1 && typeof list[0] == 'object' && list[0] instanceof Array)
            this.list = list[0];
        else
            this.list = list;
    }
    
    public print() {
        console.log(this.list);
    }
}

class B extends A {
    constructor(public name: string, ...list: Array<any>) {
        super(list);
    }
}

var b: B = new B('bob', 'red', 'green', 'blue');
b.print();
May 9, 2014 at 3:02 PM
Here's another way:
class A {
    private list: Array<any>;
    
    constructor(list: Array<any>);
    constructor(...list: Array<any>); 
    constructor(list?: any) {
        if (arguments.length == 1 && typeof list == 'object' && list instanceof Array)
            this._initialize.apply(this, list);
        else
            this._initialize.apply(this, arguments);
    }
    
    private _initialize(...list: Array<any>) {
        this.list = list;
    }
    
    public print() {
        console.log(this.list);
    }
}

class B extends A {
    constructor(public name: string, ...list: Array<any>) {
        super(list);
    }
}

var b: B = new B('bob', 'red', 'green', 'blue');
b.print();
May 12, 2014 at 7:29 AM
Cheers for the help James, that last solution is a fairly nice way of getting around the problem. With a little bit of tinkering it should do the job.
May 12, 2014 at 7:54 AM
Thanks, glad I could help. ;)