-
Notifications
You must be signed in to change notification settings - Fork 12.8k
preset class properties to undefined #12437
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
Comments
You need to explicitly initialise them as undefined to have the effect you want. Input class ImplicitlyUndefinedProperties {
public foo: string;
public bar: string;
}
class ExplicitlyUndefinedProperties {
public foo: string = undefined;
public bar: string = undefined;
} Output var ImplicitlyUndefinedProperties = (function () {
function ImplicitlyUndefinedProperties() {
}
return ImplicitlyUndefinedProperties;
}());
var ExplicitlyUndefinedProperties = (function () {
function ExplicitlyUndefinedProperties() {
this.foo = undefined;
this.bar = undefined;
}
return ExplicitlyUndefinedProperties;
}()); Therefore I think that this is not an issue but is intended behaviour. |
While this is the original/current behavior, the current ES proposal seems to actually imply that a property will indeed be defined & set to https://tc39.github.io/proposal-class-public-fields/#initialize-public-static-fields |
The proposal is now Stage 3 with this behavior. We need to discuss whether or not to take a break for this |
(Public) class fields are enabled by default in Chrome 72 with the initializer semantics outlined above. This part of the spec is extremely unlikely to change. Current topics of debate are just how private fields should work AFAICT. Can we please revisit and get a decision here? While the Babel transform is not officially supported, they would want to wait for a decision by the TypeScript team before implementing any fixes: babel/babel#9105 The major arguments for keeping the current semantics to me are:
In favor of switching:
Any input would be much appreciated |
For type-only information something like this could work: class Foo {
public x: string; // initialized to undefined
declare public y: string; // type-only
} |
@nicolo-ribaudo not sure how it's possible, tried it on ts playground and got |
@kutomer I think what @nicolo-ribaudo wanted to express is that the |
Yeah exactly |
Also worth noting here that moving to spec compliance is a loud breaking change, because the existing types end up being wrong with class Foo {
public x: string; // initialized to undefined
} ☝️ would be wrong; the type would need to be: class Foo {
public x?: string; // initialized to undefined
} This will be a non-trivial breaking change to a lot of codebases. (It intersects with definite |
Case in point, this breaks angularjs (tested with 1.5.11) bindings to components:
Works with tsc (angularjs initializes $ctrl.foo) but fails with @babel/typescript ($ctrl.foo is initialized as undefined and angularjs does not overwrite it). |
@vbraun It's an AngularJS bug already fixed in 1.6. Previously AngularJS sets binding properties even before the constructor being invoked, making it totally incompatible with ES class (only work when compiled to ES5, which doesn't really keep class semantics). In 1.5, you'll need to manually set the option to |
I suggested the |
@chriskrycho this doesn't have to be a breaking change. Right now the following code is considered valid (unless class Foo {
public x: string;
public getX(): string {
return x;
}
} But this can clearly cause runtime issues because I suggest declaring the property and setting it to |
You’re partly correct, but there are ways that people with That said, deferring it to |
Could I propose that only fields whose types include So this should be fine: class Foo {
public x?: string; // initialized to undefined
} and this should be an error: class Foo {
public x: string; // TypeError -- x can't be undefined
} |
Any news on this? This kind of behavior is as important as common and standard. Would be great to fix it. |
What is the use case for this one? type LolRly = { prop?: bool }
const A: LolRly = {}
const B: LolRly = { prop: undefined }
console.log(typeof A.prop) // undefined
console.log(typeof B.prop) // undefined
console.log(JSON.stringify(A)) // {}
console.log(JSON.stringify(B)) // {} If you want to do some dirty, 5-minute life hacks with iterating over an object properties (and I can smell from a mile, that it's exactly what you're trying to do), then |
@IgorSzymanski the difference, however, is observable, and it's important for it to be correct. |
@ljharb I ask again for the use case. Also, the OP example is horrible. If you define a property as non-optional |
Anything using object spread or |
Then initialise your properties explicitly. This is a breaking change, it breaks the logic behind explicit property initialisation and, once again, I do not see any use case where it should matter. I also do not see, why you would want to run a class instance against Give me a valid example of why the lack of implicit property initialisation in a class instance is an issue. |
@IgorSzymanski this continual moving of the goalposts isn't indicative of a good-faith conversation. If you don't think it's important to you, that's fine, but no one is required to justify spec compliance as a valid goal |
The reason I initially came across this issue, and wrote my comment above, is that I hit a case where an error was caused by this surprising logic. Unfortunately I cannot remember the exact example, but any similar example would be equivalent: if one writes
and doesn't initialize the property, there should be some sort of warning. Otherwise
leads to confusion. For instance, sometimes one uses
which fails if |
Any update on the spec compliance? |
This is now the behavior under |
Is that also now the default in tsc init? |
Not yet, but we should probably change that. |
Should this be reopened to track that, or would you prefer a separate issue? |
Separate issue please. Thanks! |
Filed #43167. |
Looks like there’s already #39311. |
TypeScript Version: 2.1.1
Code
Expected behavior:
Actual behavior:
class PartialPolicySearchIten { }
The problem comes when using Reflection it can't find the properties. I would expected that the properties exists as i'm redefining them. Otherwise their very little point is declaring properties of a class.
The text was updated successfully, but these errors were encountered: