Skip to content
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

Preserve type aliases for union and intersection types #42149

Merged
merged 32 commits into from
Jan 9, 2021

Conversation

ahejlsberg
Copy link
Member

@ahejlsberg ahejlsberg commented Dec 29, 2020

With this PR we improve preservation of type aliases for union and intersection types. Previously, an alias associated with a union type was lost when that type was made part of another union. For example:

type Shape =
    | { kind: "circle", radius: number }
    | { kind: "square", size: number }
    | { kind: "rectangle", width: number, height: number };

type Named = { name: string };

declare let shape: Shape;  // Shape
declare let optionalShape: Shape | undefined;  // Shape | undefined
declare let namedShape: Shape & Named;  // Shape & Named
declare let optionalNamedShape: Shape & Named | undefined;  // (Shape & Named) | undefined

Previously, the types of all but the shape variable would be displayed as fully expanded unions (see in playground). Now, the types are displayed as they were written. This makes diagnostics involving these types significantly easier to comprehend.

This PR also makes it possible to have distinct aliases for the same union or intersection types. For example:

type StrOrNum1 = string | number;
type StrOrNum2 = string | number;

declare let sn1: StrOrNum1;  // StrOrNum1
declare let sn2: StrOrNum2;  // StrOrNum2

Previously we'd show the alias StrOrNum1 for both sn1 and sn2.

The key implementation change in the PR is that we now include alias symbols in the key used to intern union, intersection, and indexed access types. Thus, aliased forms of these types get a separate type identity. We additionally include an "origin" description in union types when the originating declaration has fewer constituents than the fully expanded and normalized union. This origin may actually be an intersection, as is the case in the type (A | B | C) & (D | E | F). A slight performance impact is expected because we now create more type identities for equivalent unions.

Fixes #35654.

@typescript-bot typescript-bot added Author: Team For Uncommitted Bug PR for untriaged, rejected, closed or missing bug labels Dec 29, 2020
@ahejlsberg
Copy link
Member Author

@typescript-bot test this
@typescript-bot user test this
@typescript-bot run dt
@typescript-bot perf test this

@typescript-bot
Copy link
Collaborator

typescript-bot commented Dec 29, 2020

Heya @ahejlsberg, I've started to run the perf test suite on this PR at 237e9ca. You can monitor the build here.

Update: The results are in!

@typescript-bot
Copy link
Collaborator

typescript-bot commented Dec 29, 2020

Heya @ahejlsberg, I've started to run the parallelized community code test suite on this PR at 237e9ca. You can monitor the build here.

@typescript-bot
Copy link
Collaborator

typescript-bot commented Dec 29, 2020

Heya @ahejlsberg, I've started to run the extended test suite on this PR at 237e9ca. You can monitor the build here.

@typescript-bot
Copy link
Collaborator

typescript-bot commented Dec 29, 2020

Heya @ahejlsberg, I've started to run the parallelized Definitely Typed test suite on this PR at 237e9ca. You can monitor the build here.

@typescript-bot
Copy link
Collaborator

@ahejlsberg
The results of the perf run you requested are in!

Here they are:

Comparison Report - master..42149

Metric master 42149 Delta Best Worst
Angular - node (v10.16.3, x64)
Memory used 345,422k (± 0.02%) 345,510k (± 0.02%) +89k (+ 0.03%) 345,348k 345,721k
Parse Time 1.98s (± 0.44%) 1.98s (± 0.53%) 0.00s ( 0.00%) 1.95s 2.00s
Bind Time 0.84s (± 0.99%) 0.83s (± 0.74%) -0.01s (- 0.72%) 0.82s 0.84s
Check Time 4.98s (± 0.70%) 4.99s (± 0.44%) +0.01s (+ 0.28%) 4.94s 5.03s
Emit Time 5.33s (± 0.74%) 5.36s (± 0.63%) +0.03s (+ 0.53%) 5.28s 5.43s
Total Time 13.13s (± 0.57%) 13.16s (± 0.36%) +0.04s (+ 0.27%) 13.03s 13.24s
Compiler-Unions - node (v10.16.3, x64)
Memory used 205,761k (± 0.09%) 207,111k (± 0.08%) +1,350k (+ 0.66%) 206,491k 207,248k
Parse Time 0.80s (± 0.84%) 0.79s (± 1.07%) -0.01s (- 0.75%) 0.78s 0.81s
Bind Time 0.51s (± 1.64%) 0.50s (± 1.40%) -0.01s (- 1.19%) 0.48s 0.51s
Check Time 12.21s (± 1.13%) 12.47s (± 1.13%) +0.26s (+ 2.14%) 12.22s 12.79s
Emit Time 2.34s (± 1.39%) 2.33s (± 1.16%) -0.01s (- 0.43%) 2.29s 2.41s
Total Time 15.85s (± 0.93%) 16.09s (± 0.99%) +0.24s (+ 1.53%) 15.82s 16.50s
Monaco - node (v10.16.3, x64)
Memory used 354,953k (± 0.02%) 355,003k (± 0.02%) +50k (+ 0.01%) 354,854k 355,173k
Parse Time 1.60s (± 0.40%) 1.59s (± 0.59%) -0.01s (- 0.56%) 1.57s 1.61s
Bind Time 0.73s (± 0.94%) 0.73s (± 0.61%) +0.00s (+ 0.28%) 0.72s 0.74s
Check Time 5.10s (± 0.46%) 5.13s (± 0.55%) +0.03s (+ 0.55%) 5.07s 5.21s
Emit Time 2.82s (± 0.55%) 2.81s (± 0.73%) -0.01s (- 0.46%) 2.77s 2.88s
Total Time 10.25s (± 0.31%) 10.26s (± 0.47%) +0.01s (+ 0.10%) 10.20s 10.43s
TFS - node (v10.16.3, x64)
Memory used 307,983k (± 0.02%) 307,995k (± 0.01%) +12k (+ 0.00%) 307,930k 308,066k
Parse Time 1.23s (± 0.54%) 1.23s (± 0.30%) -0.00s (- 0.33%) 1.22s 1.23s
Bind Time 0.68s (± 0.53%) 0.68s (± 0.99%) -0.01s (- 1.02%) 0.66s 0.69s
Check Time 4.58s (± 0.51%) 4.54s (± 0.45%) -0.04s (- 0.85%) 4.50s 4.59s
Emit Time 2.92s (± 0.85%) 2.92s (± 0.93%) +0.01s (+ 0.21%) 2.86s 2.99s
Total Time 9.42s (± 0.37%) 9.37s (± 0.45%) -0.05s (- 0.49%) 9.28s 9.49s
material-ui - node (v10.16.3, x64)
Memory used 490,194k (± 0.01%) 494,252k (± 0.02%) +4,058k (+ 0.83%) 494,058k 494,474k
Parse Time 2.06s (± 0.41%) 2.05s (± 0.83%) -0.01s (- 0.49%) 2.02s 2.08s
Bind Time 0.65s (± 0.56%) 0.66s (± 1.11%) +0.00s (+ 0.61%) 0.65s 0.68s
Check Time 13.60s (± 0.86%) 13.60s (± 0.67%) -0.00s (- 0.03%) 13.48s 13.94s
Emit Time 0.00s (± 0.00%) 0.00s (± 0.00%) 0.00s ( NaN%) 0.00s 0.00s
Total Time 16.32s (± 0.75%) 16.31s (± 0.62%) -0.01s (- 0.06%) 16.16s 16.68s
Angular - node (v12.1.0, x64)
Memory used 322,922k (± 0.08%) 323,135k (± 0.03%) +214k (+ 0.07%) 322,955k 323,298k
Parse Time 1.98s (± 0.56%) 1.96s (± 0.54%) -0.02s (- 0.96%) 1.94s 2.00s
Bind Time 0.83s (± 1.40%) 0.81s (± 0.80%) -0.01s (- 1.69%) 0.80s 0.83s
Check Time 4.90s (± 0.47%) 4.87s (± 0.46%) -0.02s (- 0.49%) 4.84s 4.94s
Emit Time 5.52s (± 0.85%) 5.47s (± 0.54%) -0.05s (- 0.92%) 5.42s 5.54s
Total Time 13.22s (± 0.61%) 13.12s (± 0.34%) -0.11s (- 0.81%) 13.03s 13.27s
Compiler-Unions - node (v12.1.0, x64)
Memory used 191,906k (± 0.11%) 193,230k (± 0.07%) +1,324k (+ 0.69%) 192,793k 193,415k
Parse Time 0.78s (± 0.90%) 0.78s (± 0.64%) -0.01s (- 0.77%) 0.77s 0.79s
Bind Time 0.50s (± 1.12%) 0.50s (± 0.89%) 0.00s ( 0.00%) 0.49s 0.51s
Check Time 10.88s (± 0.94%) 11.18s (± 0.60%) +0.30s (+ 2.74%) 11.08s 11.40s
Emit Time 2.38s (± 0.85%) 2.32s (± 1.02%) -0.07s (- 2.81%) 2.28s 2.36s
Total Time 14.54s (± 0.81%) 14.77s (± 0.46%) +0.22s (+ 1.55%) 14.66s 14.98s
Monaco - node (v12.1.0, x64)
Memory used 337,040k (± 0.03%) 337,097k (± 0.02%) +56k (+ 0.02%) 336,957k 337,268k
Parse Time 1.59s (± 0.61%) 1.57s (± 0.92%) -0.02s (- 1.07%) 1.55s 1.62s
Bind Time 0.71s (± 0.82%) 0.71s (± 0.95%) +0.00s (+ 0.00%) 0.70s 0.73s
Check Time 4.92s (± 0.59%) 4.90s (± 0.37%) -0.01s (- 0.31%) 4.85s 4.93s
Emit Time 2.86s (± 0.55%) 2.86s (± 0.39%) -0.00s (- 0.10%) 2.83s 2.89s
Total Time 10.08s (± 0.47%) 10.04s (± 0.24%) -0.04s (- 0.36%) 9.98s 10.08s
TFS - node (v12.1.0, x64)
Memory used 292,222k (± 0.02%) 292,254k (± 0.02%) +32k (+ 0.01%) 292,148k 292,410k
Parse Time 1.25s (± 0.49%) 1.26s (± 1.06%) +0.01s (+ 0.56%) 1.23s 1.29s
Bind Time 0.65s (± 0.52%) 0.65s (± 0.69%) -0.01s (- 0.77%) 0.64s 0.66s
Check Time 4.53s (± 0.44%) 4.50s (± 0.61%) -0.03s (- 0.66%) 4.44s 4.56s
Emit Time 2.95s (± 0.80%) 2.95s (± 0.64%) -0.01s (- 0.27%) 2.89s 2.98s
Total Time 9.38s (± 0.39%) 9.35s (± 0.42%) -0.03s (- 0.33%) 9.27s 9.45s
material-ui - node (v12.1.0, x64)
Memory used 467,935k (± 0.05%) 472,031k (± 0.01%) +4,096k (+ 0.88%) 471,949k 472,236k
Parse Time 2.07s (± 0.48%) 2.07s (± 0.57%) +0.00s (+ 0.05%) 2.04s 2.10s
Bind Time 0.64s (± 0.73%) 0.64s (± 0.63%) -0.00s (- 0.16%) 0.63s 0.65s
Check Time 12.09s (± 0.91%) 12.17s (± 0.69%) +0.08s (+ 0.65%) 11.99s 12.33s
Emit Time 0.00s (± 0.00%) 0.00s (± 0.00%) 0.00s ( NaN%) 0.00s 0.00s
Total Time 14.80s (± 0.79%) 14.88s (± 0.54%) +0.08s (+ 0.51%) 14.72s 15.05s
Angular - node (v8.9.0, x64)
Memory used 348,084k (± 0.01%) 348,165k (± 0.02%) +81k (+ 0.02%) 348,061k 348,282k
Parse Time 2.51s (± 0.83%) 2.51s (± 0.34%) -0.00s (- 0.12%) 2.49s 2.53s
Bind Time 0.87s (± 0.42%) 0.87s (± 0.69%) 0.00s ( 0.00%) 0.85s 0.88s
Check Time 5.60s (± 0.54%) 5.59s (± 0.75%) -0.01s (- 0.18%) 5.51s 5.68s
Emit Time 6.31s (± 0.72%) 6.33s (± 0.88%) +0.02s (+ 0.25%) 6.23s 6.43s
Total Time 15.30s (± 0.44%) 15.30s (± 0.48%) -0.00s (- 0.02%) 15.12s 15.48s
Compiler-Unions - node (v8.9.0, x64)
Memory used 213,573k (± 0.03%) 214,928k (± 0.01%) +1,356k (+ 0.63%) 214,870k 214,998k
Parse Time 0.96s (± 0.61%) 0.96s (± 0.50%) 0.00s ( 0.00%) 0.95s 0.97s
Bind Time 0.57s (± 0.59%) 0.57s (± 0.97%) -0.00s (- 0.17%) 0.56s 0.58s
Check Time 14.90s (± 0.64%) 15.28s (± 0.77%) +0.38s (+ 2.58%) 15.06s 15.55s
Emit Time 2.77s (± 2.20%) 2.75s (± 1.15%) -0.01s (- 0.40%) 2.64s 2.81s
Total Time 19.20s (± 0.61%) 19.57s (± 0.67%) +0.37s (+ 1.93%) 19.30s 19.88s
Monaco - node (v8.9.0, x64)
Memory used 358,878k (± 0.01%) 358,879k (± 0.01%) +1k (+ 0.00%) 358,784k 358,995k
Parse Time 1.92s (± 0.39%) 1.93s (± 0.60%) +0.00s (+ 0.21%) 1.91s 1.97s
Bind Time 0.91s (± 0.61%) 0.91s (± 0.63%) -0.00s (- 0.22%) 0.90s 0.92s
Check Time 5.66s (± 0.42%) 5.66s (± 0.48%) +0.01s (+ 0.12%) 5.61s 5.72s
Emit Time 3.43s (± 0.57%) 3.42s (± 0.34%) -0.01s (- 0.32%) 3.40s 3.45s
Total Time 11.93s (± 0.24%) 11.93s (± 0.27%) 0.00s ( 0.00%) 11.86s 12.02s
TFS - node (v8.9.0, x64)
Memory used 310,574k (± 0.01%) 310,638k (± 0.02%) +64k (+ 0.02%) 310,552k 310,760k
Parse Time 1.57s (± 0.74%) 1.57s (± 0.58%) +0.00s (+ 0.19%) 1.56s 1.60s
Bind Time 0.68s (± 0.85%) 0.68s (± 0.65%) -0.00s (- 0.15%) 0.67s 0.69s
Check Time 5.33s (± 0.56%) 5.31s (± 0.63%) -0.03s (- 0.47%) 5.26s 5.38s
Emit Time 2.98s (± 1.18%) 2.96s (± 1.02%) -0.02s (- 0.74%) 2.88s 3.00s
Total Time 10.56s (± 0.58%) 10.52s (± 0.49%) -0.05s (- 0.45%) 10.40s 10.62s
material-ui - node (v8.9.0, x64)
Memory used 497,412k (± 0.01%) 501,579k (± 0.01%) +4,166k (+ 0.84%) 501,489k 501,622k
Parse Time 2.50s (± 0.40%) 2.48s (± 0.32%) -0.02s (- 0.72%) 2.46s 2.50s
Bind Time 0.81s (± 1.37%) 0.81s (± 1.03%) -0.01s (- 1.11%) 0.79s 0.83s
Check Time 18.32s (± 0.81%) 17.93s (± 0.54%) -0.39s (- 2.15%) 17.73s 18.14s
Emit Time 0.00s (± 0.00%) 0.00s (± 0.00%) 0.00s ( NaN%) 0.00s 0.00s
Total Time 21.63s (± 0.66%) 21.21s (± 0.48%) -0.42s (- 1.95%) 21.00s 21.42s
Angular - node (v8.9.0, x86)
Memory used 199,883k (± 0.03%) 199,856k (± 0.02%) -27k (- 0.01%) 199,760k 199,992k
Parse Time 2.44s (± 0.44%) 2.43s (± 0.84%) -0.01s (- 0.29%) 2.40s 2.49s
Bind Time 1.01s (± 0.87%) 1.01s (± 0.94%) -0.01s (- 0.59%) 0.98s 1.02s
Check Time 5.08s (± 0.71%) 5.04s (± 0.38%) -0.03s (- 0.65%) 5.00s 5.10s
Emit Time 6.15s (± 1.19%) 6.10s (± 0.65%) -0.05s (- 0.78%) 6.03s 6.19s
Total Time 14.68s (± 0.53%) 14.58s (± 0.42%) -0.10s (- 0.66%) 14.45s 14.70s
Compiler-Unions - node (v8.9.0, x86)
Memory used 128,569k (± 0.02%) 129,236k (± 0.05%) +667k (+ 0.52%) 129,144k 129,382k
Parse Time 0.96s (± 0.68%) 0.96s (± 1.20%) +0.01s (+ 0.63%) 0.95s 0.99s
Bind Time 0.50s (± 1.23%) 0.50s (± 0.68%) -0.00s (- 0.80%) 0.49s 0.50s
Check Time 13.96s (± 0.81%) 14.18s (± 0.37%) +0.21s (+ 1.52%) 14.07s 14.32s
Emit Time 2.62s (± 1.80%) 2.62s (± 2.56%) +0.01s (+ 0.23%) 2.53s 2.80s
Total Time 18.04s (± 0.70%) 18.26s (± 0.54%) +0.22s (+ 1.21%) 18.06s 18.46s
Monaco - node (v8.9.0, x86)
Memory used 203,341k (± 0.02%) 203,368k (± 0.02%) +27k (+ 0.01%) 203,274k 203,492k
Parse Time 1.97s (± 0.86%) 1.96s (± 0.78%) -0.01s (- 0.41%) 1.94s 2.00s
Bind Time 0.71s (± 0.42%) 0.72s (± 0.72%) +0.01s (+ 1.26%) 0.71s 0.73s
Check Time 5.81s (± 1.50%) 5.72s (± 1.70%) -0.09s (- 1.50%) 5.50s 5.86s
Emit Time 2.80s (± 3.05%) 2.83s (± 3.70%) +0.03s (+ 1.11%) 2.72s 3.09s
Total Time 11.30s (± 0.35%) 11.24s (± 0.17%) -0.05s (- 0.49%) 11.20s 11.30s
TFS - node (v8.9.0, x86)
Memory used 177,720k (± 0.02%) 177,750k (± 0.02%) +30k (+ 0.02%) 177,684k 177,803k
Parse Time 1.62s (± 1.48%) 1.63s (± 1.95%) +0.01s (+ 0.62%) 1.59s 1.73s
Bind Time 0.65s (± 0.51%) 0.66s (± 1.77%) +0.01s (+ 0.92%) 0.64s 0.69s
Check Time 4.88s (± 0.43%) 4.86s (± 0.42%) -0.01s (- 0.27%) 4.81s 4.91s
Emit Time 2.85s (± 1.43%) 2.84s (± 1.02%) -0.01s (- 0.35%) 2.75s 2.89s
Total Time 10.00s (± 0.73%) 9.99s (± 0.50%) -0.01s (- 0.06%) 9.85s 10.12s
material-ui - node (v8.9.0, x86)
Memory used 280,291k (± 0.02%) 282,410k (± 0.01%) +2,119k (+ 0.76%) 282,318k 282,479k
Parse Time 2.55s (± 0.68%) 2.54s (± 0.58%) -0.01s (- 0.47%) 2.51s 2.57s
Bind Time 0.71s (± 4.59%) 0.72s (± 5.69%) +0.01s (+ 0.98%) 0.69s 0.83s
Check Time 16.61s (± 0.78%) 16.61s (± 0.65%) -0.00s (- 0.01%) 16.38s 16.87s
Emit Time 0.00s (± 0.00%) 0.00s (± 0.00%) 0.00s ( NaN%) 0.00s 0.00s
Total Time 19.87s (± 0.74%) 19.87s (± 0.60%) +0.00s (+ 0.01%) 19.70s 20.25s
System
Machine Namets-ci-ubuntu
Platformlinux 4.4.0-197-generic
Architecturex64
Available Memory16 GB
Available Memory9 GB
CPUs4 × Intel(R) Core(TM) i7-4770 CPU @ 3.40GHz
Hosts
  • node (v10.16.3, x64)
  • node (v12.1.0, x64)
  • node (v8.9.0, x64)
  • node (v8.9.0, x86)
Scenarios
  • Angular - node (v10.16.3, x64)
  • Angular - node (v12.1.0, x64)
  • Angular - node (v8.9.0, x64)
  • Angular - node (v8.9.0, x86)
  • Compiler-Unions - node (v10.16.3, x64)
  • Compiler-Unions - node (v12.1.0, x64)
  • Compiler-Unions - node (v8.9.0, x64)
  • Compiler-Unions - node (v8.9.0, x86)
  • Monaco - node (v10.16.3, x64)
  • Monaco - node (v12.1.0, x64)
  • Monaco - node (v8.9.0, x64)
  • Monaco - node (v8.9.0, x86)
  • TFS - node (v10.16.3, x64)
  • TFS - node (v12.1.0, x64)
  • TFS - node (v8.9.0, x64)
  • TFS - node (v8.9.0, x86)
  • material-ui - node (v10.16.3, x64)
  • material-ui - node (v12.1.0, x64)
  • material-ui - node (v8.9.0, x64)
  • material-ui - node (v8.9.0, x86)
Benchmark Name Iterations
Current 42149 10
Baseline master 10

@typescript-bot
Copy link
Collaborator

The user suite test run you requested has finished and failed. I've opened a PR with the baseline diff from master.

@ahejlsberg
Copy link
Member Author

@typescript-bot test this
@typescript-bot user test this
@typescript-bot run dt
@typescript-bot perf test this

@typescript-bot
Copy link
Collaborator

typescript-bot commented Jan 1, 2021

Heya @ahejlsberg, I've started to run the parallelized community code test suite on this PR at e0d4774. You can monitor the build here.

@typescript-bot
Copy link
Collaborator

typescript-bot commented Jan 1, 2021

Heya @ahejlsberg, I've started to run the perf test suite on this PR at e0d4774. You can monitor the build here.

Update: The results are in!

@ahejlsberg
Copy link
Member Author

Meanwhile, once the test runs finish I will merge this PR.

@ahejlsberg ahejlsberg merged commit 6aeb8c1 into master Jan 9, 2021
@robpalme
Copy link

robpalme commented Jan 9, 2021

@robpalme With latest commits we permit a new type alias to be associated with an instantiation of another type alias. That fixes the issue with Color vs. MakeEnum<...>.

I have tested e794cb9 that included "Allow new alias to be associated with type alias instantiation". It's wonderful. It entirely solves the size regression I reported earlier 🎉 Not only that, it cleans up even more instances of the MakeEnum pattern. The full isolated effect of that (now-reverted) specific commit when compared to the final PR is...

  • 30 declaration files out of 394 were affected by this specific commit
  • Net size of all declaration files shrank by 31KB
    • 30 files shrank (total size of these files reduced by 31KB from 500KB to 469KB)
      • One particularly troublesome file reduced from 43KB to 33KB
    • 0 files grew

I reviewed every emit change. It's spot on every single time, resulting in ideal emit, i.e. an expanded union is replaced by a reference to an identifier that is already in scope. As an example, the emit introduced by this now-merged PR...

// dts emit from PR#42149
   myColorProp: MakeEnum<{
        readonly red: "red";
        readonly green: "green";
        readonly blue: "blue";
    }>;

...is now replaced with this...

// dts emit from e794cb9 "Allow new alias to be associated with type alias instantiation"
   myColorProp: Color;

This makes the declaration files smaller and easier to read. And it helps prevent inter-project staleness issues. And it will help our documentation generation pipeline that reads the .d.ts files to generate correctly linked HTML. Your work on this is highly appreciated.

@DanielRosenwasser DanielRosenwasser deleted the preserveTypeAliases branch January 11, 2021 19:07
Zzzen pushed a commit to Zzzen/TypeScript that referenced this pull request Jan 16, 2021
* Create separate types for equivalent aliased unions

* Accept new baselines

* Preserve original types for union types

* Accept new baselines

* Preserve intersection origin for union types

* Accept new baselines

* Accept new baselines

* Preserve aliases during relationship checks

* Accept new baselines

* Preserve aliases for intersection and indexed access types

* Accept new baselines

* Compute intersection-of-unions cross product without recursion

* Accept new baselines

* Use denormalized type objects for origin / support 'keyof' origins

* Accept new baselines

* Fix fourslash test

* Recursively extract named union types

* Accept new baselines

* Map on union origin in mapType to better preserve aliases and origins

* Remove redundant call

* Accept new baselines

* Revert back to declared type when branches produce equivalent union

* Accept new baselines

* Don't include denormal origin types in regular type statistics

* Fix issue with unions not being marked primitive-only

* Allow new alias to be associated with type alias instantiation

* Accept new baselines

* Revert "Accept new baselines"

This reverts commit 4507270.

* Revert "Allow new alias to be associated with type alias instantiation"

This reverts commit 2c2d06d.
@OliverJAsh
Copy link
Contributor

OliverJAsh commented Feb 16, 2021

FYI: I'm upgrading some projects to use TypeScript 4.2 RC and this change is causing issues with $ExpectType tests (dtslint). Because the alias name is preserved, it is no longer possible to write tests that check the structure of a type.

Reduced test case (this worked in TS 4.1):

type Compact<A> = A extends Function ? A : { [K in keyof A]: A[K] } & {};

type DistributiveOmit<T, K extends keyof T> = T extends unknown ? Omit<T, K> : never;

type Base<T> = T & { base: string };
type A = { a: string };
type B = { b: string };
type C = (Base<A> | Base<B>) & { toRemove: string };

// Given properties outside of the union, it should omit
// $ExpectType { a: string; base: string; } | { b: string; base: string; }
type Test1 = Compact<DistributiveOmit<C, 'toRemove'>>;

… but it fails in TS 4.2:

ERROR: 32:1   expect                       [email protected] expected type to be:
  { a: string; base: string; } | { b: string; base: string; }
got:
  Test1

I'm not sure there is any way for me to rewrite this test?

I think this is going to cause issues for tests in the DefinitelyTyped repo.

@DanielRosenwasser
Copy link
Member

@ahejlsberg @RyanCavanaugh @orta @sandersn, I think @OliverJAsh has a point. It looks like we still haven't provided API users with a way to opt out of printing origin types. This means we're probably unprepared for divergences in type display between 4.1 and 4.2+ in DefinitelyTyped.

@OliverJAsh
Copy link
Contributor

@DanielRosenwasser Now that 4.2 is out I guess we might start running into issues…

@sandersn
Copy link
Member

I don't understand the problem well enough yet: does this only cause a problem for API users who have been using text equality on the output of type display? I feel like that's a bad idea anyway, and something that dtslint should stop eventually, switching instead to something like tsd.

@weswigham
Copy link
Member

weswigham commented Feb 25, 2021

I mean, DT does type text comparison (heh), but it does support specifying multiple allowable representations, since we have textual representation changes somewhat regularly. (On DT, we can say // $ExpectType A || B<T>)

@OliverJAsh
Copy link
Contributor

OliverJAsh commented Mar 16, 2021

does this only cause a problem for API users who have been using text equality on the output of type display? I feel like that's a bad idea anyway, and something that dtslint should stop eventually, switching instead to something like tsd.

I completely agree, but as it stands this is what DefinitelyTyped is using—so after TS 4.2, many tests in DefinitelyTyped will no longer function correctly, and there's no way to rewrite them without significantly changing the behaviour of the test. In my example above, we want to test the structure, not the name of the test. This was possible before because TS printed the whole structure, but now it does not.

Until dtslint changes its testing infrastructure, I feel like we need an escape hatch so that these tests can continue to function.

@sandersn
Copy link
Member

So far DT has taken the other option of adding synonyms, so I don't think an escape hatch is needed for dtslint at least [1]. A quick scan shows 667 uses of the || syntax, the majority of which are because of alias [non]usage. It's not an ideal situation, but it's a small fraction of the almost 27,000 uses of $ExpectType.

[1] An interactive expansion of aliases in quickinfo would be nice though.

@OliverJAsh
Copy link
Contributor

So far DT has taken the other option of adding synonyms

I saw your PR which added a bunch of these (DefinitelyTyped/DefinitelyTyped#50566). I'm concerned that this could cause problems in the future. These synonyms are not testing the same thing, so in the future when the tests are only ran with TypeScript versions 4.2 and above, these tests could pass when they should fail.

For example, I could modify my example test from above:

 type Compact<A> = A extends Function ? A : { [K in keyof A]: A[K] } & {};
 
-type DistributiveOmit<T, K extends keyof T> = T extends unknown ? Omit<T, K> : never;
+type DistributiveOmit<T, K extends keyof T> = T;
 
 type Base<T> = T & { base: string };
 type A = { a: string };
 type B = { b: string };
 type C = (Base<A> | Base<B>) & { toRemove: string };
 
 // Given properties outside of the union, it should omit
-// $ExpectType { a: string; base: string; } | { b: string; base: string; }
+// $ExpectType { a: string; base: string; } | { b: string; base: string; } || Test1
 type Test1 = Compact<DistributiveOmit<C, 'toRemove'>>;

I've deliberately broken DistributiveOmit, but this test will still pass in TS 4.2.

@sandersn
Copy link
Member

The reason I'm not worried about DefinitelyTyped/DefinitelyTyped#50566 is that those $ExpectType uses are for values, where testing the alias is probably better, since the important part is that the value has a particular type, not that the type has particular structure.

As you point out in your original example, type testing via type alias becomes tautological after this PR. || Test1 will never fail, so it's not a valid way to update the tests in the first place.

@simeyla
Copy link

simeyla commented Jun 21, 2021

@ahejlsberg Here's another situation where this behavior may be undesirable.

Sometimes I'll use a type as a sort of lookup for related sub types (where I can't justify creating a named type for each). For example:

type AnimalDefinitions = {
    dog: { bark: boolean},
    cat: { meow: boolean},
    camel: { canFitThroughEyeOfNeedle: false }
}

I can then create a type that behaves like an enum of the different animals:

 type AnimalType = keyof AnimalDefinitions;   // "dog" | "cat" | "camel"

In TS 4.1 if I hover my cursor over AnimalType I see:

type AnimalType = "dog" | "cat" | "camel"

But in TS 4.2 it's now obviously going to become the less desirable:

type AnimalType = keyof AnimalDefinitions

Fortunately when I type the following I still get autocompleted suggestions (which really is why I'm doing this in the first place):

const animal: AnimalType = 

So some sort of opt out would be very valuable for this case too.

This is the first idea off the top of my head. Could such a helper be created today?

type AnimalType = Resolve<keyof AnimalDefinitions>;   // should be  "dog" | "cat" | "camel"

@ahejlsberg
Copy link
Member Author

Could such a helper be created today?

The following should do the trick:

type Resolve<T> = T extends T ? T : never;

@captain-yossarian
Copy link

There is might be a bug which was provided between TS 4.1.5 and 4.2.3.
See this question

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Author: Team For Uncommitted Bug PR for untriaged, rejected, closed or missing bug
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

[Feature Request] Future-proof always-aliasing/never-expanding of mapped/intersection/union/etc. types