Christian Todd Christian Todd - 1 month ago 8
Javascript Question

TypeScript class inheritance constructor confusion

I'm working through the book Eloquent Javascript and I've hit a bit of a snag with an end of chapter exercise. I decided early on that I would use TypeScript primarily to tackle these exercises on top of vanilla JS just to expose myself to the extra features TS affords me.

The full exercise can be found here: http://eloquentjavascript.net/06_object.html#h_nLNNevzcF7

As I see it, I'm supposed to essentially extend a pre-existing class that has been defined by the author within this chapter which I have done my best to re-write in TypeScript to leverage classes:

//from textbook.

function repeat(string: string, times: number): string {
var result = '';
for (var i = 0; i < times; i++)
result += string;
return result;
}

//inferred from textbook.

class TextCell {
text: any;
constructor(text: string) {
this.text = text.split('');
}
minWidth(): number {
return this.text.reduce((width: number, line: any) => Math.max(width, line.length), 0);
}
minHeight(): number {
return this.text.length;
}
draw(width: number, height: number) : any[]{
var result: any[] = [];
for (var i = 0; i < height; i++) {
var line = this.text[i] || '';
result.push(line + repeat(' ', width - line.length));
}
return result;
}
}


And here is my extension of that class:

class StretchCell extends TextCell {
width: number;
height: number;
constructor(text: any, width: number, height: number) {
super(text);
this.width = width;
this.height = height;
}

minWidth(): number {
return Math.max(this.width, super.minWidth());
}
minHeight(): number {
return Math.max(this.height, super.minHeight());
}
draw(width: number, height: number): any[] {
return super.draw(this.width, this.height);
}
}


The 'tests' that are run are:

var sc = new StretchCell(new TextCell('abc'), 1, 2);

console.log(sc.minWidth());
// → 3
console.log(sc.minHeight());
// → 2
console.log(sc.draw(3, 2));
// → ['abc', ' ']


I'm not currently getting any output at all, instead I'm getting:
TypeError: text.split is not a function
. I know I'm getting this error because I'm attempting to call .split() on a type other than a string, but I'm not sure where in my code that the
text
is being coerced into a different type and causing this error to be thrown.

I have a sneaking suspicion that my issue lies within the constructors of the classes, but it's unclear to me. Any insight into the composition of my code would be greatly appreciated. This is also my first time using TypeScript classes and inheritance, so expect some newbie mistakes.

Answer

This code in extension class constructor

constructor(text: any, width: number, height: number) {
    super(text);

passes text directly to pre-existing class constructor by calling super(text). So text here is supposed to be a string, because that's how it's declared in pre-existing TextCell constructor.

But when you create instance of StretchCell class, you are passing TextCell object instance for text parameter, not a string. This is the reason for text.split is not a function error - TextCell has no method called split.

The extension class constructor should be declared as

constructor(text: string, width: number, height: number) {
    super(text);

and StretchCell instance has to be created like this:

var sc = new StretchCell('abc', 1, 2);