-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Improve intersection reduction and CFA for truthy, equality, and typeof checks #49119
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Conversation
@typescript-bot test this |
Heya @ahejlsberg, I've started to run the abridged perf test suite on this PR at 39326d7. You can monitor the build here. Update: The results are in! |
Heya @ahejlsberg, I've started to run the parallelized Definitely Typed test suite on this PR at 39326d7. You can monitor the build here. |
Heya @ahejlsberg, I've started to run the extended test suite on this PR at 39326d7. You can monitor the build here. |
Heya @ahejlsberg, I've started to run the diff-based community code test suite on this PR at 39326d7. You can monitor the build here. Update: The results are in! |
@ahejlsberg Here they are:Comparison Report - main..refs/pull/49119/merge [async]1 of 1 projects failed to build with the old tsc /mnt/ts_downloads/async/tsconfig.json
|
@ahejlsberg Here they are:Comparison Report - main..49119
System
Hosts
Scenarios
Developer Information: |
@typescript-bot test this |
Heya @ahejlsberg, I've started to run the abridged perf test suite on this PR at 986963c. You can monitor the build here. Update: The results are in! |
Heya @ahejlsberg, I've started to run the parallelized Definitely Typed test suite on this PR at 986963c. You can monitor the build here. |
Heya @ahejlsberg, I've started to run the diff-based community code test suite on this PR at 986963c. You can monitor the build here. |
Heya @ahejlsberg, I've started to run the extended test suite on this PR at 986963c. You can monitor the build here. |
@ahejlsberg Here they are:Comparison Report - main..49119
System
Hosts
Scenarios
Developer Information: |
@user test this inline |
Is there a reason why this narrowing wasn't implemented for |
I feel like that's an oversight and probably deserves its own issue. (But, I'm not Anders 😄) |
It seems that in the examples in the main message in the function f5<T>(x: T) {
...
if (x !== undefined && x !== null) {
x; // {} -- should be T & {}
}
else {
x; // T
}
if (x != undefined) {
x; // {} -- should be NonNullable<T>
}
else {
x; // T
}
if (x != null) {
x; // {} -- should be NonNullable<T>
}
else {
x; // T
}
} But this is clear from the context and will not confuse anyone too much, I think. |
This PR introduces a number of changes affecting control flow analysis of truthy, equality, and typeof checks involving type
unknown
and unconstrained type variables in--strictNullChecks
mode. Key to these changes is the fact that{}
, the empty object type literal, is a supertype of all types exceptnull
andundefined
. Thus,{} | null | undefined
is effectively equivalent tounknown
, and for an arbitrary typeT
, the intersectionT & {}
represents the non-nullable form ofT
.The PR introduces the following new behaviors:
{}
.NonNullable<T>
is now an alias forT & {}
.T & {}
, whereT
is non-generic and notnull
orundefined
, reduces to justT
(null & {}
andundefined & {}
already reduce tonever
). See below for exceptions forstring & {}
,number & {}
, andbigint & {}
.undefined & void
reduces to justundefined
.{}
,null
, andundefined
.unknown
behaves similarly to the union type{} | null | undefined
.{}
in the true branch.null
orundefined
, generic types are intersected with{}
,{} | null
, or{} | undefined
in the false branch.typeof x === "object"
expressions, generic types are intersected withobject
and/ornull
in the true branch (typeof
checks for other types already produce intersections in a similar manner).Some examples:
Note the manner in which types are properly inferred, combined, and reduced in the
ensureNotXXX
functions. This contrasts with theNonNullable<T>
conditional type provided inlib.d.ts
, which unfortunately combines and reduces poorly. For example,NonNullable<NonNullable<T>>
doesn't inherently reduce toNonNullable<T>
, sometimes leading to needlessly complex types. For this and other reasons we intend to investigate switchingNonNullable<T>
to be an alias forT & {}
.For backwards compatibility, special exceptions to the
T & {}
type reduction rules existing for intersections written explicitly asstring & {}
,number & {}
, andbigint & {}
(as opposed to created through instantiation of a generic typeT & {}
). These types are used in a few frameworks (e.g.react
andcsstype
) to construct types that permit anystring
,number
, orbigint
, but has statement completion hints for common literal values. For example:The special
string & {}
type prevents subtype reduction from taking place in the union type, thus preserving the literal types, but otherwise anystring
value is assignable to the type.This PR reinstatates #48366 (which was removed from 4.7 due to concerns over breaking changes).
Fixes #23368.
Fixes #31908.
Fixes #32347.
Fixes #43997.
Fixes #44446.
Fixes #48048.
Fixes #48468.
Fixes #48691.
Fixes #49005.
Fixes #49191.