-
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
Improve intersection reduction and CFA for truthy, equality, and typeof checks #49119
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.