-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
Check non-undefined properties are initialized in the constructor with --strictNullChecks
#8476
Comments
Since we're not able to track assignment effects between methods, we'd break code that calls a separate 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. |
under a flag then? |
Yeah, probably something like |
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. |
ummm.... class NonAbstractClass { // <-- Non-abstract class, so can be instantiated by itself
readonly imNotInitialized: number; // <-- can only be initialized here
constructor() {
// <-- or here
}
} class Base {
readonly imNotInitializedToTheRightType: any;
constructor() {
this.imNotInitializedToTheRightType = "hi";
}
}
class Derived extends Base {
readonly imNotInitializedToTheRightType: number; // <-- is this initialized?
constructor() {
super();
}
} |
I think I've shown one common scenario where this would be a help, not an irritant: namely 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 |
Yes, we might be able to do something for |
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:
|
I'd also add that if the purpose of non-nullable types is to ensure that a value (be it an argument, variable, or property) can never be null, then the lack of such checks in constructors effectively defeats the purpose of the feature. Swift is very strict on this matter and IMHO gets it right - if you tell the compiler that the type of a given value cannot be null, you are guaranteed this will be the case. Omitting such checks on properties at initialization time severely limits the utility of this feature, particularly given that it's likely that potentially uninitialised properties can be assigned to values which have a non-nullable type, thus violating the guarantees that the type system supposedly guarantees. In the following code,
|
Is this feature definitely not getting implemented then? I've been really excited about I also think that anyone who's irritated by this will also be irritated enough in general about strict null checking, that they are likely not to use it anyway. |
Please re-consider adding this feature (default off and turned on with IMO this is a big potential source of errors, have stumbled on this issue only 4 days after switching to strict null checks (which is awesome btw). |
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 // under a flag like `--auto_init_properties`
class Person {
id: number; // auto initialized to 0
name: 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 = new Option();
} In this way, all properties are actually defined in runtime: const obj = new Person();
for (const property in obj) {
console.log(property);
}
// Output: id, name, description, opt Also, we don't need to write boilerplate code to enforce strict type safety: class Person {
constructor {
this.id = 0;
this.name = '';
this.description = null;
this.opt = new Option();
}
} Started a new issues at #19750 |
This suggestion is now implemented by #20075. |
@ahejlsberg thank you for keeping an open mind. all the work of the team over some big milestones has been greatly appreciated. |
A huge win for TypeScript. Thank you so much for listening to feedback and for your efforts on this!! |
The text was updated successfully, but these errors were encountered: