Skip to content

Preserve type aliases for union and intersection types - #42149

Merged
ahejlsberg merged 32 commits into
masterfrom
preserveTypeAliases
Jan 9, 2021
Merged

Preserve type aliases for union and intersection types#42149
ahejlsberg merged 32 commits into
masterfrom
preserveTypeAliases

Conversation

@ahejlsberg

@ahejlsbergahejlsberg commented Dec 29, 2020

Copy link
Copy Markdown
Member

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-bottypescript-bot added Author: Team For Uncommitted Bug PR for untriaged, rejected, closed or missing bug labels Dec 29, 2020
@ahejlsberg

Copy link
Copy Markdown
MemberAuthor

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

@typescript-bot

typescript-bot commented Dec 29, 2020

Copy link
Copy Markdown
Contributor

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

typescript-bot commented Dec 29, 2020

Copy link
Copy Markdown
Contributor

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

typescript-bot commented Dec 29, 2020

Copy link
Copy Markdown
Contributor

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

@typescript-bot

typescript-bot commented Dec 29, 2020

Copy link
Copy Markdown
Contributor

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
Copy Markdown
Contributor

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

Here they are:

Comparison Report - master..42149

Metricmaster42149DeltaBestWorst
Angular - node (v10.16.3, x64)
Memory used345,422k (± 0.02%)345,510k (± 0.02%)+89k (+ 0.03%)345,348k345,721k
Parse Time1.98s (± 0.44%)1.98s (± 0.53%)0.00s ( 0.00%)1.95s2.00s
Bind Time0.84s (± 0.99%)0.83s (± 0.74%)-0.01s (- 0.72%)0.82s0.84s
Check Time4.98s (± 0.70%)4.99s (± 0.44%)+0.01s (+ 0.28%)4.94s5.03s
Emit Time5.33s (± 0.74%)5.36s (± 0.63%)+0.03s (+ 0.53%)5.28s5.43s
Total Time13.13s (± 0.57%)13.16s (± 0.36%)+0.04s (+ 0.27%)13.03s13.24s
Compiler-Unions - node (v10.16.3, x64)
Memory used205,761k (± 0.09%)207,111k (± 0.08%)+1,350k (+ 0.66%)206,491k207,248k
Parse Time0.80s (± 0.84%)0.79s (± 1.07%)-0.01s (- 0.75%)0.78s0.81s
Bind Time0.51s (± 1.64%)0.50s (± 1.40%)-0.01s (- 1.19%)0.48s0.51s
Check Time12.21s (± 1.13%)12.47s (± 1.13%)+0.26s (+ 2.14%)12.22s12.79s
Emit Time2.34s (± 1.39%)2.33s (± 1.16%)-0.01s (- 0.43%)2.29s2.41s
Total Time15.85s (± 0.93%)16.09s (± 0.99%)+0.24s (+ 1.53%)15.82s16.50s
Monaco - node (v10.16.3, x64)
Memory used354,953k (± 0.02%)355,003k (± 0.02%)+50k (+ 0.01%)354,854k355,173k
Parse Time1.60s (± 0.40%)1.59s (± 0.59%)-0.01s (- 0.56%)1.57s1.61s
Bind Time0.73s (± 0.94%)0.73s (± 0.61%)+0.00s (+ 0.28%)0.72s0.74s
Check Time5.10s (± 0.46%)5.13s (± 0.55%)+0.03s (+ 0.55%)5.07s5.21s
Emit Time2.82s (± 0.55%)2.81s (± 0.73%)-0.01s (- 0.46%)2.77s2.88s
Total Time10.25s (± 0.31%)10.26s (± 0.47%)+0.01s (+ 0.10%)10.20s10.43s
TFS - node (v10.16.3, x64)
Memory used307,983k (± 0.02%)307,995k (± 0.01%)+12k (+ 0.00%)307,930k308,066k
Parse Time1.23s (± 0.54%)1.23s (± 0.30%)-0.00s (- 0.33%)1.22s1.23s
Bind Time0.68s (± 0.53%)0.68s (± 0.99%)-0.01s (- 1.02%)0.66s0.69s
Check Time4.58s (± 0.51%)4.54s (± 0.45%)-0.04s (- 0.85%)4.50s4.59s
Emit Time2.92s (± 0.85%)2.92s (± 0.93%)+0.01s (+ 0.21%)2.86s2.99s
Total Time9.42s (± 0.37%)9.37s (± 0.45%)-0.05s (- 0.49%)9.28s9.49s
material-ui - node (v10.16.3, x64)
Memory used490,194k (± 0.01%)494,252k (± 0.02%)+4,058k (+ 0.83%)494,058k494,474k
Parse Time2.06s (± 0.41%)2.05s (± 0.83%)-0.01s (- 0.49%)2.02s2.08s
Bind Time0.65s (± 0.56%)0.66s (± 1.11%)+0.00s (+ 0.61%)0.65s0.68s
Check Time13.60s (± 0.86%)13.60s (± 0.67%)-0.00s (- 0.03%)13.48s13.94s
Emit Time0.00s (± 0.00%)0.00s (± 0.00%)0.00s ( NaN%)0.00s0.00s
Total Time16.32s (± 0.75%)16.31s (± 0.62%)-0.01s (- 0.06%)16.16s16.68s
Angular - node (v12.1.0, x64)
Memory used322,922k (± 0.08%)323,135k (± 0.03%)+214k (+ 0.07%)322,955k323,298k
Parse Time1.98s (± 0.56%)1.96s (± 0.54%)-0.02s (- 0.96%)1.94s2.00s
Bind Time0.83s (± 1.40%)0.81s (± 0.80%)-0.01s (- 1.69%)0.80s0.83s
Check Time4.90s (± 0.47%)4.87s (± 0.46%)-0.02s (- 0.49%)4.84s4.94s
Emit Time5.52s (± 0.85%)5.47s (± 0.54%)-0.05s (- 0.92%)5.42s5.54s
Total Time13.22s (± 0.61%)13.12s (± 0.34%)-0.11s (- 0.81%)13.03s13.27s
Compiler-Unions - node (v12.1.0, x64)
Memory used191,906k (± 0.11%)193,230k (± 0.07%)+1,324k (+ 0.69%)192,793k193,415k
Parse Time0.78s (± 0.90%)0.78s (± 0.64%)-0.01s (- 0.77%)0.77s0.79s
Bind Time0.50s (± 1.12%)0.50s (± 0.89%)0.00s ( 0.00%)0.49s0.51s
Check Time10.88s (± 0.94%)11.18s (± 0.60%)+0.30s (+ 2.74%)11.08s11.40s
Emit Time2.38s (± 0.85%)2.32s (± 1.02%)-0.07s (- 2.81%)2.28s2.36s
Total Time14.54s (± 0.81%)14.77s (± 0.46%)+0.22s (+ 1.55%)14.66s14.98s
Monaco - node (v12.1.0, x64)
Memory used337,040k (± 0.03%)337,097k (± 0.02%)+56k (+ 0.02%)336,957k337,268k
Parse Time1.59s (± 0.61%)1.57s (± 0.92%)-0.02s (- 1.07%)1.55s1.62s
Bind Time0.71s (± 0.82%)0.71s (± 0.95%)+0.00s (+ 0.00%)0.70s0.73s
Check Time4.92s (± 0.59%)4.90s (± 0.37%)-0.01s (- 0.31%)4.85s4.93s
Emit Time2.86s (± 0.55%)2.86s (± 0.39%)-0.00s (- 0.10%)2.83s2.89s
Total Time10.08s (± 0.47%)10.04s (± 0.24%)-0.04s (- 0.36%)9.98s10.08s
TFS - node (v12.1.0, x64)
Memory used292,222k (± 0.02%)292,254k (± 0.02%)+32k (+ 0.01%)292,148k292,410k
Parse Time1.25s (± 0.49%)1.26s (± 1.06%)+0.01s (+ 0.56%)1.23s1.29s
Bind Time0.65s (± 0.52%)0.65s (± 0.69%)-0.01s (- 0.77%)0.64s0.66s
Check Time4.53s (± 0.44%)4.50s (± 0.61%)-0.03s (- 0.66%)4.44s4.56s
Emit Time2.95s (± 0.80%)2.95s (± 0.64%)-0.01s (- 0.27%)2.89s2.98s
Total Time9.38s (± 0.39%)9.35s (± 0.42%)-0.03s (- 0.33%)9.27s9.45s
material-ui - node (v12.1.0, x64)
Memory used467,935k (± 0.05%)472,031k (± 0.01%)+4,096k (+ 0.88%)471,949k472,236k
Parse Time2.07s (± 0.48%)2.07s (± 0.57%)+0.00s (+ 0.05%)2.04s2.10s
Bind Time0.64s (± 0.73%)0.64s (± 0.63%)-0.00s (- 0.16%)0.63s0.65s
Check Time12.09s (± 0.91%)12.17s (± 0.69%)+0.08s (+ 0.65%)11.99s12.33s
Emit Time0.00s (± 0.00%)0.00s (± 0.00%)0.00s ( NaN%)0.00s0.00s
Total Time14.80s (± 0.79%)14.88s (± 0.54%)+0.08s (+ 0.51%)14.72s15.05s
Angular - node (v8.9.0, x64)
Memory used348,084k (± 0.01%)348,165k (± 0.02%)+81k (+ 0.02%)348,061k348,282k
Parse Time2.51s (± 0.83%)2.51s (± 0.34%)-0.00s (- 0.12%)2.49s2.53s
Bind Time0.87s (± 0.42%)0.87s (± 0.69%)0.00s ( 0.00%)0.85s0.88s
Check Time5.60s (± 0.54%)5.59s (± 0.75%)-0.01s (- 0.18%)5.51s5.68s
Emit Time6.31s (± 0.72%)6.33s (± 0.88%)+0.02s (+ 0.25%)6.23s6.43s
Total Time15.30s (± 0.44%)15.30s (± 0.48%)-0.00s (- 0.02%)15.12s15.48s
Compiler-Unions - node (v8.9.0, x64)
Memory used213,573k (± 0.03%)214,928k (± 0.01%)+1,356k (+ 0.63%)214,870k214,998k
Parse Time0.96s (± 0.61%)0.96s (± 0.50%)0.00s ( 0.00%)0.95s0.97s
Bind Time0.57s (± 0.59%)0.57s (± 0.97%)-0.00s (- 0.17%)0.56s0.58s
Check Time14.90s (± 0.64%)15.28s (± 0.77%)+0.38s (+ 2.58%)15.06s15.55s
Emit Time2.77s (± 2.20%)2.75s (± 1.15%)-0.01s (- 0.40%)2.64s2.81s
Total Time19.20s (± 0.61%)19.57s (± 0.67%)+0.37s (+ 1.93%)19.30s19.88s
Monaco - node (v8.9.0, x64)
Memory used358,878k (± 0.01%)358,879k (± 0.01%)+1k (+ 0.00%)358,784k358,995k
Parse Time1.92s (± 0.39%)1.93s (± 0.60%)+0.00s (+ 0.21%)1.91s1.97s
Bind Time0.91s (± 0.61%)0.91s (± 0.63%)-0.00s (- 0.22%)0.90s0.92s
Check Time5.66s (± 0.42%)5.66s (± 0.48%)+0.01s (+ 0.12%)5.61s5.72s
Emit Time3.43s (± 0.57%)3.42s (± 0.34%)-0.01s (- 0.32%)3.40s3.45s
Total Time11.93s (± 0.24%)11.93s (± 0.27%)0.00s ( 0.00%)11.86s12.02s
TFS - node (v8.9.0, x64)
Memory used310,574k (± 0.01%)310,638k (± 0.02%)+64k (+ 0.02%)310,552k310,760k
Parse Time1.57s (± 0.74%)1.57s (± 0.58%)+0.00s (+ 0.19%)1.56s1.60s
Bind Time0.68s (± 0.85%)0.68s (± 0.65%)-0.00s (- 0.15%)0.67s0.69s
Check Time5.33s (± 0.56%)5.31s (± 0.63%)-0.03s (- 0.47%)5.26s5.38s
Emit Time2.98s (± 1.18%)2.96s (± 1.02%)-0.02s (- 0.74%)2.88s3.00s
Total Time10.56s (± 0.58%)10.52s (± 0.49%)-0.05s (- 0.45%)10.40s10.62s
material-ui - node (v8.9.0, x64)
Memory used497,412k (± 0.01%)501,579k (± 0.01%)+4,166k (+ 0.84%)501,489k501,622k
Parse Time2.50s (± 0.40%)2.48s (± 0.32%)-0.02s (- 0.72%)2.46s2.50s
Bind Time0.81s (± 1.37%)0.81s (± 1.03%)-0.01s (- 1.11%)0.79s0.83s
Check Time18.32s (± 0.81%)17.93s (± 0.54%)-0.39s (- 2.15%)17.73s18.14s
Emit Time0.00s (± 0.00%)0.00s (± 0.00%)0.00s ( NaN%)0.00s0.00s
Total Time21.63s (± 0.66%)21.21s (± 0.48%)-0.42s (- 1.95%)21.00s21.42s
Angular - node (v8.9.0, x86)
Memory used199,883k (± 0.03%)199,856k (± 0.02%)-27k (- 0.01%)199,760k199,992k
Parse Time2.44s (± 0.44%)2.43s (± 0.84%)-0.01s (- 0.29%)2.40s2.49s
Bind Time1.01s (± 0.87%)1.01s (± 0.94%)-0.01s (- 0.59%)0.98s1.02s
Check Time5.08s (± 0.71%)5.04s (± 0.38%)-0.03s (- 0.65%)5.00s5.10s
Emit Time6.15s (± 1.19%)6.10s (± 0.65%)-0.05s (- 0.78%)6.03s6.19s
Total Time14.68s (± 0.53%)14.58s (± 0.42%)-0.10s (- 0.66%)14.45s14.70s
Compiler-Unions - node (v8.9.0, x86)
Memory used128,569k (± 0.02%)129,236k (± 0.05%)+667k (+ 0.52%)129,144k129,382k
Parse Time0.96s (± 0.68%)0.96s (± 1.20%)+0.01s (+ 0.63%)0.95s0.99s
Bind Time0.50s (± 1.23%)0.50s (± 0.68%)-0.00s (- 0.80%)0.49s0.50s
Check Time13.96s (± 0.81%)14.18s (± 0.37%)+0.21s (+ 1.52%)14.07s14.32s
Emit Time2.62s (± 1.80%)2.62s (± 2.56%)+0.01s (+ 0.23%)2.53s2.80s
Total Time18.04s (± 0.70%)18.26s (± 0.54%)+0.22s (+ 1.21%)18.06s18.46s
Monaco - node (v8.9.0, x86)
Memory used203,341k (± 0.02%)203,368k (± 0.02%)+27k (+ 0.01%)203,274k203,492k
Parse Time1.97s (± 0.86%)1.96s (± 0.78%)-0.01s (- 0.41%)1.94s2.00s
Bind Time0.71s (± 0.42%)0.72s (± 0.72%)+0.01s (+ 1.26%)0.71s0.73s
Check Time5.81s (± 1.50%)5.72s (± 1.70%)-0.09s (- 1.50%)5.50s5.86s
Emit Time2.80s (± 3.05%)2.83s (± 3.70%)+0.03s (+ 1.11%)2.72s3.09s
Total Time11.30s (± 0.35%)11.24s (± 0.17%)-0.05s (- 0.49%)11.20s11.30s
TFS - node (v8.9.0, x86)
Memory used177,720k (± 0.02%)177,750k (± 0.02%)+30k (+ 0.02%)177,684k177,803k
Parse Time1.62s (± 1.48%)1.63s (± 1.95%)+0.01s (+ 0.62%)1.59s1.73s
Bind Time0.65s (± 0.51%)0.66s (± 1.77%)+0.01s (+ 0.92%)0.64s0.69s
Check Time4.88s (± 0.43%)4.86s (± 0.42%)-0.01s (- 0.27%)4.81s4.91s
Emit Time2.85s (± 1.43%)2.84s (± 1.02%)-0.01s (- 0.35%)2.75s2.89s
Total Time10.00s (± 0.73%)9.99s (± 0.50%)-0.01s (- 0.06%)9.85s10.12s
material-ui - node (v8.9.0, x86)
Memory used280,291k (± 0.02%)282,410k (± 0.01%)+2,119k (+ 0.76%)282,318k282,479k
Parse Time2.55s (± 0.68%)2.54s (± 0.58%)-0.01s (- 0.47%)2.51s2.57s
Bind Time0.71s (± 4.59%)0.72s (± 5.69%)+0.01s (+ 0.98%)0.69s0.83s
Check Time16.61s (± 0.78%)16.61s (± 0.65%)-0.00s (- 0.01%)16.38s16.87s
Emit Time0.00s (± 0.00%)0.00s (± 0.00%)0.00s ( NaN%)0.00s0.00s
Total Time19.87s (± 0.74%)19.87s (± 0.60%)+0.00s (+ 0.01%)19.70s20.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)
BenchmarkNameIterations
Current4214910
Baselinemaster10

@typescript-bot

Copy link
Copy Markdown
Contributor

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
Copy Markdown
MemberAuthor

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

@typescript-bot

typescript-bot commented Jan 1, 2021

Copy link
Copy Markdown
Contributor

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

typescript-bot commented Jan 1, 2021

Copy link
Copy Markdown
Contributor

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
ahejlsberg merged commit 6aeb8c1 into masterJan 9, 2021
@robpalme

Copy link
Copy Markdown

@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<{readonlyred: "red";readonlygreen: "green";readonlyblue: "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

OliverJAsh commented Feb 16, 2021

Copy link
Copy Markdown
Contributor

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):

typeCompact<A>=AextendsFunction ? A : {[KinkeyofA]: A[K]}&{};typeDistributiveOmit<T,KextendskeyofT>=Textendsunknown ? Omit<T,K> : never;typeBase<T>=T&{base: string};typeA={a: string};typeB={b: string};typeC=(Base<A>|Base<B>)&{toRemove: string};// Given properties outside of the union, it should omit// $ExpectType { a: string; base: string; } | { b: string; base: string; }typeTest1=Compact<DistributiveOmit<C,'toRemove'>>;

… but it fails in TS 4.2:

ERROR: 32:1 expect TypeScript@4.3 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
Copy Markdown
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
Copy Markdown
Contributor

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

@sandersn

Copy link
Copy Markdown
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

weswigham commented Feb 25, 2021

Copy link
Copy Markdown
Member

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

OliverJAsh commented Mar 16, 2021

Copy link
Copy Markdown
Contributor

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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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

simeyla commented Jun 21, 2021

Copy link
Copy Markdown

@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
Copy Markdown
MemberAuthor

Could such a helper be created today?

The following should do the trick:

typeResolve<T>=TextendsT ? T : never;

@captain-yossarian

Copy link
Copy Markdown

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

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Author: TeamFor Uncommitted BugPR 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

13 participants

@ahejlsberg@typescript-bot@DanielRosenwasser@orta@robpalme@treybrisbane@rbuckton@OliverJAsh@sandersn@weswigham@simeyla@captain-yossarian@RyanCavanaugh