-
Notifications
You must be signed in to change notification settings - Fork 12.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow to call getter/setter logic When subclassing #338
Comments
The problem is that we don't surface the fact that a property is a getter/setter in the type information, and it's impossible to emit code here that would work even if the base class's definition was not a getter/setter. Using 'virtual' properties in JavaScript is generally not a good idea for this reason. /* MyDeclFile.d.ts */
declare class A {
x: number; // actually implemented as getter/setter
y: number; // actually implemented as field
}
/* MyConsumer.ts */
class B {
get x() { return super.x; } // Could theoretically emit code for this
get y() { return super.y; } // Cannot work; there is no 'super.y' to refer to
} |
It's part of es6 class, so it seems pretty important to me, also generating something that throws an error in case of missing super setter and return undefined in case of missing super getter (like what traceur does https://github.com/google/traceur-compiler/blob/master/src/runtime/classes.js#L43-L60) seems pretty much standard and compliant with what future es6 engine will do. |
The point about ES6 is very important. We'll need to figure out what that means. |
I think it means that we'll support |
Just for info, why the traceur runtime code portion that I pointed is not considered a good solution ? Like the |
I have two concerns: First, the performance of a |
What if we lookup getters and setters only once, right before defining property ? For example like this. |
Another possibility is to only allow it when emitting in ES6? |
When I try a super property reference in the Playground, it gives me a compiler error but seems to work fine at runtime. Is this just a question of eliminating the compiler error? I'm sure I'm missing something, so please enlighten me! |
Sorry, I just answered my own question. It only works in that trivial example, where there is no reference to the instance state of the derived class. |
Hi, Any update about this issue ? |
For the record, when we transitioned from Babel to TypeScript, I wrote this custom transformer + runtime patch. It's a bit of hack from a transformation perspective, but I believe it is semantically correct in behavior (and preserved our super accessor functionality as compiled with babel):
runtime patch:
The runtime semantics require no knowledge of types or super class implementations. Obviously to put this in TypeScript proper, you would want that code to be generated, and/or in tslib, not patched on |
Thanks for reopening, @RyanCavanaugh — this is a problematic issue and readily worked around, per e.g. the patch by @kriszyp |
Long story short - after five years of not having this and people surviving despite it, it seems like ES6 adoption is catching up fast enough that the narrow window of people who target ES5 (rather than 3 for maximum compat or 6 for smallest emit delta) is closing to the point where we don't want to accept a big chunk of helper emit at this point. Open to data otherwise but it just doesn't seem common enough to warrant a big change in the emitter. |
Just a data point: This is a blocker to using Typescript to compile Knockout.js version 4. The depth of workaround needed is uncertain, but it feels problematic. Cross-linking knockout/tko#21 |
I'm just curious, but when I put the following code into the playground, the output JS seems legit to me (and it works):
Does this mean, access to super's property works, but the compiler is still complaining? |
@ThomasdenH It's references to class Foo {
constructor () { this.x = 'dee' }
get bar() {
return 'foo' + this.x;
}
}
class Bar extends Foo {
get bar() {
return super.bar + 'bar';
}
}
const foo = new Foo()
const bar = new Bar();
alert(`foo: ${foo.bar}, bar: ${bar.bar}`) The output above is |
@brianmhunt Brrr, I see. Good catch. |
@brianmhunt Little typo there: The output above is |
@SlurpTheo Yes, you're correct; edited my comment to fix; thanks! |
http://typescript.codeplex.com/workitem/645
At the moment it's not possible to call super getter/setter when overriding properties:
The text was updated successfully, but these errors were encountered: