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
Ambient public fields initialized in parent class are blocked at compile-time #35327
Comments
Interestingly, the error is correct, but only because the canonical (i.e. untransformed) emit is apparently wrong. With "use strict";
// @useDefineForClassFields: true
// @target: esnext
class Parent {
a;
constructor(arg) {
this.a = arg;
}
}
class Child extends Parent {
a;
constructor(arg) {
super(arg);
console.log(this.a); // Property 'a' is used before being assigned. (2565)
}
}
new Child(3); // prints undefined
|
It seems the emit was fixed post-3.7, as the ambient field isn't emitted after switching the Playground to |
You're right @fatcerberus that the original issue #34972 has now been fixed on master. Upon testing that fix I then discovered this compile-time error, so raised it here. |
It's just very interesting that the error message is correct for the original (incorrect) behavior. |
Good point. I guess it's obvious in retrospect, because the fix only changed the transformer. There was no change to the checker. |
Thanks for scheduling this @RyanCavanaugh. This feature ( |
Previously these were incorrectly treated just like normal properties: ```ts class Parent { a: any; constructor(arg: any) { this.a = arg; } } class Child extends Parent { declare a: number; constructor(arg: number) { super(arg); console.log(this.a); // Property 'a' is used before being assigned. (2565) } } ``` Fixes #35327
Previously these were incorrectly treated just like normal properties: ```ts class Parent { a: any; constructor(arg: any) { this.a = arg; } } class Child extends Parent { declare a: number; constructor(arg: number) { super(arg); console.log(this.a); // Property 'a' is used before being assigned. (2565) } } ``` Fixes #35327
Previously these were incorrectly treated just like normal properties: ```ts class Parent { a: any; constructor(arg: any) { this.a = arg; } } class Child extends Parent { declare a: number; constructor(arg: number) { super(arg); console.log(this.a); // Property 'a' is used before being assigned. (2565) } } ``` Fixes microsoft#35327
TypeScript Version: 3.8.0-dev.20191123
Search Terms: ambient declare public class fields parent initializer useDefineForClassFields
Code:
Expected behavior:
There should be no compile-time error, because this is legitimate ES(next) code. The intent of
declare <field>
is merely to specialize the type, not to impose additional initialization constraints.Actual behavior:
The usage of
this.a
causes the compiler errorProperty 'a' is used before being assigned. (2565)
.The emitted code is good. The only problem is the compile-time error.
Playground Link:
Related Issues: #34972
The main use-case for ambient public fields is to specialize parent class fields. It is common for parent class fields to only be initialized in the parent constructor, invoked via
super()
. Due to this bug, this pattern does not work today, forcing the use of a workaround such as using@ts-ignore
or redundant re-initialization of the property in the child constructor to appease the compiler.cc: @sandersn
The text was updated successfully, but these errors were encountered: