-
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
Strict property initialization checks in classes #20075
Conversation
Add check for |
Is there a reason TS can't check if the called functions access the uninitialized value, then report the error in the constructor? |
@kingdaro we only do control flow analysis across function bounds for immediately invoked function expressions; to do otherwise would be error-prone in the presence of aliasing, so we conservatively avoid doing so. |
What about initializing helpers? |
@abramobagnara I'd propose one of:
|
I have edited the PR description to reflect #20166. |
Will be really useful to have a warning in such case. |
Also, does this PR handle cases where error is thrown before all fields initialised? class Car {
color: string;
constructor() {
if (!carsSupportedByBrowser) {
console.log('Cars not supported');
throw new Error('Not supported');
}
this.color = 'red';
}
} |
And a quirkier variation of previous case: class Car {
color: string;
constructor() {
if (!carsSupportedByBrowser) {
console.log('Cars not supported ', this); <--- see we expose instance with uninitialised color
throw new Error('Not supported');
}
this.color = 'red';
}
} |
It is fine to throw an exception before all properties are initialized, and yes you can expose an object that isn't fully initialized to the outside (just like you can call methods before the object is fully initialized). |
This PR implements a new
--strictPropertyInitialization
compiler option to guard against uninitialized properties in class instances. Strict property initialization checking verifies that each instance property declared in a class either (a) has a type that includesundefined
or (b) has an explicit initializer or an assignment to the property in the constructor. The--strictPropertyInitialization
option has no effect unless--strictNullChecks
is also enabled.The
--strictPropertyInitialization
switch is part of the--strict
family of switches, meaning that it defaults to on in--strict
mode. This PR is therefore a breaking change only in--strict
mode.In this example
an error is reported on property
a
because its type doesn't includeundefined
and the property declaration doesn't specify an initializer or assign a value to the property in the constructor. The error can be fixed by changing the type ofa
to includeundefined
, by specifying an initial value fora
, or by assigning a value toa
in the constructor. For example, this is ok:A strict property initialization check is satisfied by assignments in the constructor only when all possible code paths include assignments to the particular property.
In the example above, an error would occur if either of the
if
statement branches omitted the assignment tothis.a
.Strict property initialization checks guard against observing uninitialized properties in the constructor body. For example:
Strict property initialization checks also guard against observing uninitialized properties after the constructor returns. However, it is possible to observe uninitialized properties in methods that are called from the constructor (or from a base constructor). For example:
Strict property initialization checks only apply to properties that are declared with proper identifiers. It does not apply to properties with computed names or properties with names specified as string or numeric literals (this is analogous to how control flow analysis isn't applied to properties accessed using
obj["foo"]
syntax).In cases where the properties of a class instance are initialized by external means (such as dependency injection) or where it is known that an initialization method is always called before other methods, strict property initialization checks can be suppressed by including definite assignment assertions (#20166) in the declarations of the properties.
Alternatively,
// @ts-ignore
comments can be used to suppress the errors, or the code can simply be compiled without the--strictPropertyInitialization
option.Fixes #8476.