GeezerVison is showing github.com — Simplify relationship check for conditional type on target side by ahejlsberg · Pull Request #46429 · microsoft/TypeScript
Conversation
This PR simplifies our relationship checking logic for conditional types on the target side. With this PR, a source type S is assignable to a target type A extends B ? C : D when
- The conditional type is not distributive, or is distributive but
A is never referenced in C or D, and
B has no infer positions, and
S is assignable to C (except if A never assignable to B for any instantiation), and
S is assignable to D (except if A is always assignable to B for any instantiation).
The PR revises some of the logic that was added in #30639, specifically the logic that determines if A is referenced in C or D in a distributive conditional type. There are no baseline changes as a result of this PR, but it fixes the performance degradation reported in #44851.
Fixes #44851.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
DanielRosenwasser, mgcrea, timotheeguerin, omril1, and artob reacted with thumbs up emoji
gravyboat, mgcrea, and JSin reacted with heart emoji
DanielRosenwasser and kkarimi reacted with rocket emoji
DanielRosenwasser and tonivj5 reacted with eyes emoji
All reactions
-
👍
5 reactions
-
❤️
3 reactions
-
🚀
2 reactions
-
👀
2 reactions
|
I should mention that with this PR, the check time for this repro drops from ~10s to about 0.4s.
|
alexburner, LifeIsStrange, B4nan, SlurpTheo, and JeanMeche reacted with hooray emoji
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
Hurray, I helped find something maybe useful!
|
lucabezerra reacted with laugh emoji
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
|
var x: T | null = Math.random() > 0.5 ? null : t;
|
|
|
onlyNullablePlease(x); // should work
|
|
|
~
|
|
|
!!! error TS2345: Argument of type 'T | null' is not assignable to parameter of type 'null extends T | null ? any : never'.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one is interesting - is this actually a distributive conditional type? Why is it deferred?
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We always defer if either of the check and extends types contains generics. This is somewhat of a blunt instrument, and we could possibly do better in cases like this.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And by "contains generics" I mean we defer when isGenericType returns true for either of the check and extends types.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
If we're going to attempt to fix those, the fix really should be to have the conditional type construction logic decide to resolve the types instead of deferring them--but I think that has lower priority.
This is impossible in the general case - any condition with an infer has to be deferred so the infer can be instantiated with every possible input (since an infer result can't stand on its own) - if we don't reason about branch reachability in relationship checking, we can never handle conditional types that both filter and transform simultaneously like T extends () => infer I ? I : never. We knew that adding constraint checks on branch reachability would be expensive - but it's the typespace equivalent of doing control flow on genetics, which we also do wherever we can now.
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
Andrew Branch (@andrewbranch)
The results of the perf run you requested are in!
Here they are:
Comparison Report - main..46429
| Metric |
main |
46429 |
Delta |
Best |
Worst |
| Angular - node (v10.16.3, x64) |
| Memory used |
354,063k (± 0.01%) |
354,012k (± 0.02%) |
-51k (- 0.01%) |
353,868k |
354,166k |
| Parse Time |
1.96s (± 0.58%) |
1.95s (± 0.50%) |
-0.01s (- 0.46%) |
1.93s |
1.97s |
| Bind Time |
0.84s (± 0.66%) |
0.84s (± 0.81%) |
+0.00s (+ 0.36%) |
0.83s |
0.86s |
| Check Time |
5.47s (± 0.36%) |
5.48s (± 0.81%) |
+0.01s (+ 0.22%) |
5.42s |
5.61s |
| Emit Time |
5.86s (± 0.67%) |
5.88s (± 0.70%) |
+0.01s (+ 0.20%) |
5.78s |
5.98s |
| Total Time |
14.13s (± 0.34%) |
14.15s (± 0.46%) |
+0.02s (+ 0.12%) |
14.04s |
14.31s |
| Compiler-Unions - node (v10.16.3, x64) |
| Memory used |
203,871k (± 0.03%) |
203,893k (± 0.03%) |
+22k (+ 0.01%) |
203,721k |
203,980k |
| Parse Time |
0.78s (± 0.67%) |
0.78s (± 0.63%) |
+0.00s (+ 0.38%) |
0.78s |
0.80s |
| Bind Time |
0.53s (± 1.13%) |
0.52s (± 1.28%) |
-0.01s (- 1.14%) |
0.50s |
0.53s |
| Check Time |
7.95s (± 0.67%) |
7.90s (± 0.45%) |
-0.05s (- 0.62%) |
7.83s |
7.97s |
| Emit Time |
2.45s (± 0.80%) |
2.44s (± 0.65%) |
-0.01s (- 0.45%) |
2.40s |
2.48s |
| Total Time |
11.71s (± 0.46%) |
11.65s (± 0.29%) |
-0.06s (- 0.51%) |
11.56s |
11.72s |
| Monaco - node (v10.16.3, x64) |
| Memory used |
342,091k (± 0.01%) |
342,060k (± 0.03%) |
-32k (- 0.01%) |
341,822k |
342,213k |
| Parse Time |
1.48s (± 0.78%) |
1.49s (± 0.46%) |
+0.00s (+ 0.13%) |
1.47s |
1.50s |
| Bind Time |
0.75s (± 0.82%) |
0.75s (± 0.67%) |
-0.00s (- 0.53%) |
0.74s |
0.76s |
| Check Time |
5.46s (± 0.55%) |
5.42s (± 0.83%) |
-0.03s (- 0.59%) |
5.33s |
5.51s |
| Emit Time |
3.17s (± 0.70%) |
3.17s (± 0.83%) |
+0.00s (+ 0.00%) |
3.12s |
3.25s |
| Total Time |
10.86s (± 0.31%) |
10.82s (± 0.31%) |
-0.04s (- 0.33%) |
10.74s |
10.88s |
| TFS - node (v10.16.3, x64) |
| Memory used |
304,751k (± 0.01%) |
304,803k (± 0.02%) |
+52k (+ 0.02%) |
304,682k |
304,886k |
| Parse Time |
1.20s (± 0.68%) |
1.19s (± 0.25%) |
-0.01s (- 0.42%) |
1.19s |
1.20s |
| Bind Time |
0.71s (± 0.70%) |
0.71s (± 0.56%) |
+0.00s (+ 0.71%) |
0.70s |
0.72s |
| Check Time |
4.97s (± 0.51%) |
4.95s (± 0.67%) |
-0.02s (- 0.38%) |
4.88s |
5.03s |
| Emit Time |
3.30s (± 1.07%) |
3.32s (± 1.02%) |
+0.02s (+ 0.45%) |
3.26s |
3.40s |
| Total Time |
10.17s (± 0.45%) |
10.17s (± 0.44%) |
-0.01s (- 0.06%) |
10.10s |
10.28s |
| material-ui - node (v10.16.3, x64) |
| Memory used |
471,094k (± 0.02%) |
469,960k (± 0.01%) |
-1,134k (- 0.24%) |
469,861k |
470,042k |
| Parse Time |
1.77s (± 0.56%) |
1.77s (± 0.42%) |
-0.00s (- 0.17%) |
1.76s |
1.79s |
| Bind Time |
0.66s (± 1.23%) |
0.66s (± 1.22%) |
-0.00s (- 0.30%) |
0.64s |
0.68s |
| Check Time |
14.38s (± 0.41%) |
14.34s (± 0.56%) |
-0.04s (- 0.31%) |
14.18s |
14.58s |
| Emit Time |
0.00s (± 0.00%) |
0.00s (± 0.00%) |
0.00s ( NaN%) |
0.00s |
0.00s |
| Total Time |
16.82s (± 0.39%) |
16.77s (± 0.52%) |
-0.05s (- 0.32%) |
16.59s |
17.02s |
| Angular - node (v12.1.0, x64) |
| Memory used |
331,719k (± 0.08%) |
331,897k (± 0.02%) |
+178k (+ 0.05%) |
331,749k |
332,046k |
| Parse Time |
1.96s (± 0.67%) |
1.94s (± 0.51%) |
-0.02s (- 1.02%) |
1.92s |
1.97s |
| Bind Time |
0.82s (± 1.34%) |
0.82s (± 1.15%) |
0.00s ( 0.00%) |
0.80s |
0.84s |
| Check Time |
5.33s (± 0.81%) |
5.31s (± 0.38%) |
-0.02s (- 0.41%) |
5.27s |
5.36s |
| Emit Time |
6.15s (± 0.82%) |
6.09s (± 0.44%) |
-0.06s (- 0.99%) |
6.05s |
6.18s |
| Total Time |
14.26s (± 0.59%) |
14.16s (± 0.28%) |
-0.10s (- 0.72%) |
14.08s |
14.26s |
| Compiler-Unions - node (v12.1.0, x64) |
| Memory used |
191,425k (± 0.04%) |
191,331k (± 0.07%) |
-94k (- 0.05%) |
190,906k |
191,583k |
| Parse Time |
0.78s (± 0.67%) |
0.78s (± 0.93%) |
+0.00s (+ 0.13%) |
0.77s |
0.80s |
| Bind Time |
0.53s (± 0.89%) |
0.53s (± 0.71%) |
-0.01s (- 0.94%) |
0.52s |
0.53s |
| Check Time |
7.40s (± 0.55%) |
7.41s (± 0.71%) |
+0.00s (+ 0.07%) |
7.32s |
7.56s |
| Emit Time |
2.46s (± 0.85%) |
2.46s (± 1.46%) |
+0.00s (+ 0.12%) |
2.39s |
2.55s |
| Total Time |
11.17s (± 0.48%) |
11.17s (± 0.72%) |
+0.00s (+ 0.01%) |
11.02s |
11.36s |
| Monaco - node (v12.1.0, x64) |
| Memory used |
325,197k (± 0.02%) |
325,207k (± 0.02%) |
+11k (+ 0.00%) |
325,051k |
325,336k |
| Parse Time |
1.48s (± 0.91%) |
1.46s (± 0.55%) |
-0.02s (- 1.15%) |
1.45s |
1.49s |
| Bind Time |
0.73s (± 0.85%) |
0.73s (± 1.23%) |
-0.00s (- 0.41%) |
0.72s |
0.76s |
| Check Time |
5.32s (± 0.81%) |
5.33s (± 0.38%) |
+0.01s (+ 0.23%) |
5.28s |
5.39s |
| Emit Time |
3.20s (± 0.72%) |
3.18s (± 0.71%) |
-0.02s (- 0.69%) |
3.14s |
3.23s |
| Total Time |
10.73s (± 0.57%) |
10.70s (± 0.34%) |
-0.03s (- 0.25%) |
10.63s |
10.78s |
| TFS - node (v12.1.0, x64) |
| Memory used |
289,506k (± 0.02%) |
289,475k (± 0.02%) |
-31k (- 0.01%) |
289,342k |
289,574k |
| Parse Time |
1.22s (± 0.82%) |
1.21s (± 0.87%) |
-0.01s (- 0.90%) |
1.20s |
1.24s |
| Bind Time |
0.70s (± 0.86%) |
0.69s (± 1.06%) |
-0.01s (- 1.01%) |
0.68s |
0.71s |
| Check Time |
4.92s (± 0.26%) |
4.90s (± 0.56%) |
-0.02s (- 0.39%) |
4.84s |
4.96s |
| Emit Time |
3.39s (± 0.99%) |
3.37s (± 0.65%) |
-0.02s (- 0.53%) |
3.33s |
3.42s |
| Total Time |
10.23s (± 0.41%) |
10.17s (± 0.47%) |
-0.06s (- 0.57%) |
10.08s |
10.30s |
| material-ui - node (v12.1.0, x64) |
| Memory used |
449,723k (± 0.06%) |
448,617k (± 0.06%) |
-1,106k (- 0.25%) |
447,464k |
448,866k |
| Parse Time |
1.79s (± 0.91%) |
1.78s (± 0.72%) |
-0.01s (- 0.45%) |
1.76s |
1.82s |
| Bind Time |
0.65s (± 1.03%) |
0.64s (± 0.76%) |
-0.00s (- 0.46%) |
0.63s |
0.65s |
| Check Time |
13.01s (± 0.85%) |
12.97s (± 0.73%) |
-0.04s (- 0.28%) |
12.83s |
13.15s |
| Emit Time |
0.00s (± 0.00%) |
0.00s (± 0.00%) |
0.00s ( NaN%) |
0.00s |
0.00s |
| Total Time |
15.45s (± 0.73%) |
15.40s (± 0.64%) |
-0.05s (- 0.30%) |
15.23s |
15.58s |
| Angular - node (v14.15.1, x64) |
| Memory used |
330,294k (± 0.01%) |
330,303k (± 0.01%) |
+9k (+ 0.00%) |
330,268k |
330,340k |
| Parse Time |
1.96s (± 0.48%) |
1.94s (± 0.48%) |
-0.02s (- 1.27%) |
1.91s |
1.95s |
| Bind Time |
0.87s (± 0.54%) |
0.86s (± 0.39%) |
-0.01s (- 0.80%) |
0.86s |
0.87s |
| Check Time |
5.37s (± 0.44%) |
5.37s (± 0.37%) |
-0.00s (- 0.07%) |
5.32s |
5.40s |
| Emit Time |
6.19s (± 0.98%) |
6.19s (± 0.63%) |
-0.01s (- 0.10%) |
6.08s |
6.26s |
| Total Time |
14.39s (± 0.54%) |
14.35s (± 0.37%) |
-0.04s (- 0.29%) |
14.18s |
14.43s |
| Compiler-Unions - node (v14.15.1, x64) |
| Memory used |
192,554k (± 0.49%) |
192,879k (± 0.37%) |
+325k (+ 0.17%) |
189,971k |
193,279k |
| Parse Time |
0.81s (± 0.72%) |
0.81s (± 1.17%) |
+0.01s (+ 0.87%) |
0.80s |
0.84s |
| Bind Time |
0.56s (± 0.53%) |
0.55s (± 0.62%) |
-0.01s (- 0.90%) |
0.55s |
0.56s |
| Check Time |
7.60s (± 0.38%) |
7.56s (± 0.47%) |
-0.05s (- 0.63%) |
7.48s |
7.65s |
| Emit Time |
2.45s (± 0.92%) |
2.44s (± 0.82%) |
-0.01s (- 0.57%) |
2.41s |
2.50s |
| Total Time |
11.42s (± 0.33%) |
11.36s (± 0.35%) |
-0.06s (- 0.49%) |
11.29s |
11.46s |
| Monaco - node (v14.15.1, x64) |
| Memory used |
323,999k (± 0.01%) |
323,990k (± 0.01%) |
-9k (- 0.00%) |
323,951k |
324,030k |
| Parse Time |
1.51s (± 0.88%) |
1.51s (± 0.72%) |
-0.01s (- 0.46%) |
1.49s |
1.53s |
| Bind Time |
0.76s (± 0.48%) |
0.76s (± 0.48%) |
0.00s ( 0.00%) |
0.75s |
0.76s |
| Check Time |
5.33s (± 0.50%) |
5.30s (± 0.42%) |
-0.03s (- 0.53%) |
5.27s |
5.38s |
| Emit Time |
3.23s (± 0.47%) |
3.23s (± 0.68%) |
-0.00s (- 0.03%) |
3.18s |
3.27s |
| Total Time |
10.83s (± 0.36%) |
10.79s (± 0.24%) |
-0.04s (- 0.37%) |
10.73s |
10.87s |
| TFS - node (v14.15.1, x64) |
| Memory used |
288,354k (± 0.01%) |
288,339k (± 0.01%) |
-15k (- 0.01%) |
288,308k |
288,377k |
| Parse Time |
1.24s (± 0.63%) |
1.23s (± 0.53%) |
-0.01s (- 0.89%) |
1.21s |
1.24s |
| Bind Time |
0.74s (± 0.46%) |
0.73s (± 0.71%) |
-0.01s (- 1.09%) |
0.72s |
0.74s |
| Check Time |
4.94s (± 0.31%) |
4.91s (± 0.48%) |
-0.03s (- 0.57%) |
4.87s |
4.97s |
| Emit Time |
3.49s (± 0.35%) |
3.49s (± 0.82%) |
+0.01s (+ 0.17%) |
3.43s |
3.55s |
| Total Time |
10.40s (± 0.24%) |
10.36s (± 0.31%) |
-0.04s (- 0.38%) |
10.28s |
10.45s |
| material-ui - node (v14.15.1, x64) |
| Memory used |
447,964k (± 0.06%) |
446,820k (± 0.08%) |
-1,143k (- 0.26%) |
445,818k |
447,128k |
| Parse Time |
1.83s (± 0.42%) |
1.82s (± 0.49%) |
-0.01s (- 0.33%) |
1.80s |
1.85s |
| Bind Time |
0.68s (± 0.70%) |
0.68s (± 0.44%) |
+0.00s (+ 0.15%) |
0.67s |
0.68s |
| Check Time |
13.19s (± 0.94%) |
13.10s (± 0.46%) |
-0.09s (- 0.68%) |
12.97s |
13.25s |
| Emit Time |
0.00s (± 0.00%) |
0.00s (± 0.00%) |
0.00s ( NaN%) |
0.00s |
0.00s |
| Total Time |
15.70s (± 0.82%) |
15.61s (± 0.38%) |
-0.09s (- 0.59%) |
15.48s |
15.75s |
System
| Machine Name | ts-ci-ubuntu |
| Platform | linux 4.4.0-210-generic |
| Architecture | x64 |
| Available Memory | 16 GB |
| Available Memory | 6 GB |
| CPUs | 4 × Intel(R) Core(TM) i7-4770 CPU @ 3.40GHz |
Hosts
- node (v10.16.3, x64)
- node (v12.1.0, x64)
- node (v14.15.1, x64)
Scenarios
- Angular - node (v10.16.3, x64)
- Angular - node (v12.1.0, x64)
- Angular - node (v14.15.1, x64)
- Compiler-Unions - node (v10.16.3, x64)
- Compiler-Unions - node (v12.1.0, x64)
- Compiler-Unions - node (v14.15.1, x64)
- Monaco - node (v10.16.3, x64)
- Monaco - node (v12.1.0, x64)
- Monaco - node (v14.15.1, x64)
- TFS - node (v10.16.3, x64)
- TFS - node (v12.1.0, x64)
- TFS - node (v14.15.1, x64)
- material-ui - node (v10.16.3, x64)
- material-ui - node (v12.1.0, x64)
- material-ui - node (v14.15.1, x64)
| Benchmark |
Name |
Iterations |
| Current |
46429 |
10 |
| Baseline |
main |
10 |
Developer Information:Download Benchmark
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
This is impossible in the general case
Agreed, and so be it. But it does seem like there are classes of cases where we ought to do better in conditional type construction. Both of the test cases that revert back to failing with this PR seem quite trivial--for example, checking if the check and extends types are identical, or if the extends type is a union that contains the check type, would cause us to resolve the conditional type to the true case.
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
Hey Anders Hejlsberg (@ahejlsberg), I've packed this into an installable tgz. You can install it for testing by referencing it in your package.json like so:
{
"devDependencies": {
"typescript": "https://typescript.visualstudio.com/cf7ac146-d525-443c-b23c-0d58337efebc/_apis/build/builds/113306/artifacts?artifactName=tgz&fileId=A263304AC84860808E706B7F5590B0AA3616661B50F7CE35CED050B21FF1B0C802&fileName=/typescript-4.5.0-insiders.20211019.tgz"
}
}
and then running npm install.
There is also a playground for this build and an npm module you can use via "typescript": "npm:@typescript-deploys/[email protected]".;
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
I think I can say with a high degree of certainty that whatever is going on in Andrew Casey (@amcasey)'s example is unrelated. I removed all of the logic having to do with assignability to conditional types (i.e. both #30639 and this PR), and the example still blows up with an instantiation depth error.
|
andrewbranch and SlurpTheo reacted with eyes emoji
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
Please, no more plot twists, my heart can't handle it anymore.
|
SlurpTheo reacted with laugh emoji
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
Yeah, if the real world code is fast then I’m happy. Just wanted to make sure it was checked against the latest changes.
|
gravyboat and SlurpTheo reacted with hooray emoji
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
is there an example of a type that is no longer allowed as of this PR? the typescript 4.5 blog post mentions this PR
TypeScript no longer allows types to be assignable to conditional types that use infer, or that are distributive. Doing so previously often ended up causing major performance issues. For more information, see the specific change on GitHub.
but i can't seem to find a minimal example of what this means exactly
|
lucabezerra, jeremyBanks, ridesz, lukaselmer, jgbpercy, SlurpTheo, jamiegluk, and egemon reacted with thumbs up emoji
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
i18u (iahu)
commented
Dec 14, 2021
•
edited
Loading
Uh oh!
There was an error while loading. Please reload this page.
DetachHead good news (??), we found one: #47127 (comment)
This is a BAD news for me. I deeply dependency this feature. Because of this breaking change, I cant update TypeScript, it's so bad for me, could you add a compiler option to support it as a migrate plan?
|
benrbray and jarrodldavis reacted with thumbs up emoji
tonivj5 reacted with laugh emoji
All reactions
-
👍
2 reactions
-
😄
1 reaction
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Martin Probst (mprobst)
pushed a commit
to mprobst/TypeScript
that referenced
this pull request
Jan 10, 2022
…osoft#46429)
* Simplify relationship check for conditional type on target side
* Accept new baselines
* Better support for non-distribution-dependent types
* Accept new API baselines
* Accept new baselines
This was referenced Apr 18, 2022
Uh oh!
There was an error while loading. Please reload this page.
Milestone
No milestone
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
|