You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Check non-undefined properties are initialized in the constructor with --strictNullChecks #8476
Since we're not able to track assignment effects between methods, we'd break code that calls a separate initialize method (or some such) to initialize instance data. I'm not a fan of that pattern, but I have certainly run across it.
Also, presumably we want to permit uninitialized properties in abstract classes. That means we'd have to check not just locally declared properties but also inherited properties in non-abstract classes.
Yeah, probably something like --allowUninitializedProperties, but since it only happens under the new --strictNullChecks I suppose we could wait on adding the flag and gauge the feedback.
Having looked at several code bases, I don't think it is feasible to implement this feature as we have discussed it. There are simply too many common scenarios where users would need to turn the feature off if we insist that the constructor itself must initialize every non-nullable property. Effectively, it would become more of an irritant than a help.
Reacted by Joona Heikkilä, Lei Zhao, Michael Yoffe and Denis Zhbankov
Reacted by Micah Zoltu, Steven Hand, Jesse Schalken, hillin, Reinis Ivanovs, Ilya Isupov, Jakub Skořepa, Matt Mueller, Kirill Agalakov, Mariusz Pawelski and 6 more
Reacted by Nicolas HENRY, nino-porcino, Tingan Ho, Christian Pena Valerio, Yuya Tanaka, Daniel Cassidy, Daniel Li, David Rodrigue, Christian Silver, Alexander Ivanov and 10 more
classNonAbstractClass{// <-- Non-abstract class, so can be instantiated by itselfreadonlyimNotInitialized: number;// <-- can only be initialized hereconstructor(){// <-- or here}}
classBase{readonlyimNotInitializedToTheRightType: any;constructor(){this.imNotInitializedToTheRightType="hi";}}classDerivedextendsBase{readonlyimNotInitializedToTheRightType: number;// <-- is this initialized?constructor(){super();}}
Reacted by Andrew R. Gray, Max Pixel and Balazs Erdos
I think I've shown one common scenario where this would be a help, not an irritant: namelyreadonly members in a non-abstract class, and one less common, but probably more 'severe' one: inherited members initialized to incompatible or less capable types than the type they are redeclared to in a derived class.
I haven't yet got any response from you on this. Why would you think it would be an irritant here?
(also, I haven't got any responses for the questions about inheritance of readonly members by writable members and vice-versa. It has been a week so far, and neither you or anyone of the team have shown serious intentions to engage in that discussion. I can't really see a reason why not - if your original reasoning was solid it should be relatively easy to explain..)
Yes, we might be able to do something for readonly members without it being an irritant (since we already only allow assignments in initializers or the constructor).
Reacted by Aluan Haddad, Reinis Ivanovs, Dynalon, Matt Mueller, Cory Li, Philip Pham and Eugene Lubarsky
I'd be in favour of Swift's approach. A constructor is required to initialise all non-nullable properties. The compiler checks all branches to make sure this happens in every case.
As a simple example, here's a Swift class with a non-nullable field. It's required to have a constructor, because otherwise there's no way of initializing the field (this would not be the case if the type was String? instead of String). This gives the error Class 'Person' has no initializers:
class Person {
var name: String;
}
If we add an init method, but don't initialize the field, we get the following error: Return from initializer without initializing all stored properties
class Person {
var name: String;
init() {
}
}
If we have an init method which initializes the field in some branches but not others, the same error is reported: Return from initializer without initializing all stored properties
class Person {
var name: String;
init(theName: String, setName: Bool) {
if setName {
name = theName;
}
}
}
The compiler thus enforces you to initialize it in all branches:
class Person {
var name: String;
init(theName: String, setName: Bool) {
if setName {
name = theName;
}
else {
name = "Unknown";
}
}
}
Reacted by Lee Whitney, omochimetaru, Seth Brenith, Max Pixel, Oliver Uvman, Yahiko Uzumaki, Pavel Pevnitskiy, Kirill Agalakov, Pablo Gallucci and Wesley Wiser
What is the status of this? I see that the issue was dropped from TS2.6 milestone recently. Is this because of some latest design decision or the status is just unknown?
Reacted by Michael, David Rodrigue, SlurpTheo, Antoine ESTEVE, Tal Atlas and Alex Burner
What is the status of this? I see that the issue was dropped from TS2.6 milestone recently. Is this because of some latest design decision or the status is just unknown?
it is on our list of features to support. we do not have an ETA for it at the time being.
OK, as pointed out by someone in another thread, this is one of the non-goals of TypeScript.
I'd suggest that, under some flags, instead of warning user of type safety caused by the default undefined value, give it a default value like C#, if the default value can't be determined, emit an error.
// under a flag like `--auto_init_properties`classPerson{id: number;// auto initialized to 0name: string;// auto initialized to ""description: string|null;// auto initialized to null// **Compilation error: Can't determine default value for this prop, all properties must be initialized. **opt: string|number|Option;// To fix this, user must specify an value, for example:opt: string|number|Option='abc';opt: string|number|Option=newOption();}
In this way, all properties are actually defined in runtime:
Reacted by Jes Wulfsberg Nielsen, Gerard Delmàs, SlurpTheo, Sebastian Goll, omochimetaru, Kirill Agalakov, Laurence Dougal Myers, Adrian Sampson, Johan Björk, Peter Kelly and 11 more
Activity
ahejlsberg commentedon May 5, 2016
Since we're not able to track assignment effects between methods, we'd break code that calls a separate
initializemethod (or some such) to initialize instance data. I'm not a fan of that pattern, but I have certainly run across it.Also, presumably we want to permit uninitialized properties in abstract classes. That means we'd have to check not just locally declared properties but also inherited properties in non-abstract classes.
mhegazy commentedon May 5, 2016
under a flag then?
ahejlsberg commentedon May 5, 2016
Yeah, probably something like
--allowUninitializedProperties, but since it only happens under the new--strictNullChecksI suppose we could wait on adding the flag and gauge the feedback.ahejlsberg commentedon May 11, 2016
Having looked at several code bases, I don't think it is feasible to implement this feature as we have discussed it. There are simply too many common scenarios where users would need to turn the feature off if we insist that the constructor itself must initialize every non-nullable property. Effectively, it would become more of an irritant than a help.
malibuzios commentedon May 12, 2016
ummm....
malibuzios commentedon May 14, 2016
Anders Hejlsberg (@ahejlsberg)
I think I've shown one common scenario where this would be a help, not an irritant: namely
readonlymembers in a non-abstract class, and one less common, but probably more 'severe' one: inherited members initialized to incompatible or less capable types than the type they are redeclared to in a derived class.I haven't yet got any response from you on this. Why would you think it would be an irritant here?
(also, I haven't got any responses for the questions about inheritance of
readonlymembers by writable members and vice-versa. It has been a week so far, and neither you or anyone of the team have shown serious intentions to engage in that discussion. I can't really see a reason why not - if your original reasoning was solid it should be relatively easy to explain..)ahejlsberg commentedon May 14, 2016
Yes, we might be able to do something for
readonlymembers without it being an irritant (since we already only allow assignments in initializers or the constructor).peterkelly commentedon Jun 5, 2016
I'd be in favour of Swift's approach. A constructor is required to initialise all non-nullable properties. The compiler checks all branches to make sure this happens in every case.
As a simple example, here's a Swift class with a non-nullable field. It's required to have a constructor, because otherwise there's no way of initializing the field (this would not be the case if the type was String? instead of String). This gives the error Class 'Person' has no initializers:
If we add an init method, but don't initialize the field, we get the following error: Return from initializer without initializing all stored properties
If we have an init method which initializes the field in some branches but not others, the same error is reported: Return from initializer without initializing all stored properties
The compiler thus enforces you to initialize it in all branches:
74 remaining items
raveclassic commentedon Oct 9, 2017
What is the status of this? I see that the issue was dropped from TS2.6 milestone recently. Is this because of some latest design decision or the status is just unknown?
mhegazy commentedon Oct 9, 2017
it is on our list of features to support. we do not have an ETA for it at the time being.
mgenware commentedon Nov 5, 2017
OK, as pointed out by someone in another thread, this is one of the non-goals of TypeScript.
I'd suggest that, under some flags, instead of warning user of type safety caused by the default
undefinedvalue, give it a default value like C#, if the default value can't be determined, emit an error.In this way, all properties are actually defined in runtime:
Also, we don't need to write boilerplate code to enforce strict type safety:
Started a new issues at #19750
ahejlsberg commentedon Nov 16, 2017
This suggestion is now implemented by #20075.
whitneyland commentedon Nov 17, 2017
Anders Hejlsberg (@ahejlsberg) thank you for keeping an open mind. all the work of the team over some big milestones has been greatly appreciated.
peterkelly commentedon Nov 17, 2017
A huge win for TypeScript. Thank you so much for listening to feedback and for your efforts on this!!