Description
TypeScript Version: 3.3.3333 and whatever is on Playground
Search Terms: subclass getter accessor
Code
class Animal {
public get legs(): number { return -1; }
constructor(public name: string) { }
move(distanceInMeters: number = 0) {
console.log(`${this.name} moved ${distanceInMeters}m.`);
}
}
class Snake extends Animal {
public get legs(): number { return 0; } // Correct implementation of abstract superclass property
constructor(name: string) { super(name); }
move(distanceInMeters = 5) {
console.log("Slithering...");
super.move(distanceInMeters);
}
}
class Horse extends Animal {
public readonly legs: number; // Not sure if this "should" be a valid redeclaration
constructor(name: string) {
super(name);
this.legs = 4; // Works when using helper code to emulate pre-ES6 classes, fails with actual ES6
}
move(distanceInMeters = 45) {
console.log("Galloping...");
super.move(distanceInMeters);
}
}
let sam = new Snake("Sammy the Python");
let tom: Animal = new Horse("Tommy the Palomino");
sam.move();
tom.move(34);
Expected behavior: Compiler should flag the redeclaration of the getter member as a non-accessor (normal) property, at least when emitting ES6.
Actual behavior: Compiler is fine, but assignment (this.legs = 4
) fails at runtime with error about assigning to a member with getter but no setter.
Playground Link: You can paste the above into Playground to see that there are no compile-time errors but the emitted JS does not demonstrate the error because as far as I can tell, you can't tell Playground to emit ES6. (That would be a nice feature; maybe I should put in a ticket for that?)
Related Issues: none that I could find
ETA: I mistakenly had this with an abstract
getter to start with. This does not show the buggy behavior because ES6 doesn't have a concept of abstract, so the getter isn't actually defined in the generated parent class at all. The updated code above has an implementation for the getter in the base class and should show the behavior I'm talking about -- I compile it with target: 'esnext'
but I imagine it should work with target: 'es2015'
also.