Skip to content

Ensure common supertype retains nullability in inference - #49981

Closed
Jake Bailey (jakebailey) wants to merge 5 commits into
microsoft:mainfrom
jakebailey:fix-49938
Closed

Ensure common supertype retains nullability in inference#49981
Jake Bailey (jakebailey) wants to merge 5 commits into
microsoft:mainfrom
jakebailey:fix-49938

Conversation

@jakebailey

@jakebaileyJake Bailey (jakebailey) commented Jul 21, 2022

Copy link
Copy Markdown
Member

Fixes#49938

Demo: Playground Link

The common supertype of a bunch of inference candidates should include null and undefined of those candidates can be null or undefined.

#49119 and #49330 changed the way this information was stored and propagated. It turns out that the old code only worked because of a fluke related to those flags. In v4.7.4, given the types in the playground link above:

  • The candidates are B and D | undefined. We declare that these are both "primary types" because neither are exactlynull or undefined.
  • We look for the supertype of these, but because neither are supertypes of each other (because of the undefined), we end up picking B as it's the leftmost option.
  • But then, we would rescan the input types for the types whose falsy flags include null or undefined, but using a function that is recursive, so we find D | undefined, when the intent was to just find exactlynull or undefined.
  • We union that with B to get B | D | undefined, which reduces to D | undefined, and we get the supertype that everyone had expected all along, even though that's maybe not what the code was written to do!

Instead, we can just compare the candidates without null or undefined, then add null or undefined back on again if the supertype needs it; this means that the cases we supported in 4.7.4 work (and now work the same regardless of argument order).

@jakebailey

This comment was marked as outdated.

@jakebailey

This comment was marked as outdated.

@typescript-bot

This comment was marked as outdated.

@typescript-bot

This comment was marked as outdated.

@typescript-bot

This comment was marked as outdated.

@typescript-bot

This comment was marked as outdated.

@typescript-bot

This comment was marked as outdated.

@jakebailey

This comment was marked as outdated.

@typescript-bot

This comment was marked as outdated.

@typescript-bot

This comment was marked as outdated.

@typescript-bot

This comment was marked as outdated.

@jakebailey

This comment was marked as outdated.

@jakebailey
Jake Bailey (jakebailey) marked this pull request as draft July 21, 2022 17:17
@jakebailey

Copy link
Copy Markdown
MemberAuthor

Well, I narrowed this down to operate strictly on only unions and direct types, so it shouldn't have that build problem anymore (and I encoded it as a test).

@jakebailey

Copy link
Copy Markdown
MemberAuthor

@typescript-bot

TypeScript Bot (typescript-bot) commented Jul 21, 2022

Copy link
Copy Markdown
Contributor

Heya Jake Bailey (@jakebailey), I've started to run the extended test suite on this PR at a817435. You can monitor the build here.

@typescript-bot

TypeScript Bot (typescript-bot) commented Jul 21, 2022

Copy link
Copy Markdown
Contributor

Heya Jake Bailey (@jakebailey), I've started to run the diff-based user code test suite on this PR at a817435. You can monitor the build here.

Update: The results are in!

@typescript-bot

TypeScript Bot (typescript-bot) commented Jul 21, 2022

Copy link
Copy Markdown
Contributor

Heya Jake Bailey (@jakebailey), I've started to run the tarball bundle task on this PR at a817435. You can monitor the build here.

@typescript-bot

TypeScript Bot (typescript-bot) commented Jul 21, 2022

Copy link
Copy Markdown
Contributor

Hey Jake Bailey (@jakebailey), 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/130164/artifacts?artifactName=tgz&fileId=32A768F7B0A1960DB14C832B8F12F2972D738FB3A5CC18B69F843EBC2D78CBD902&fileName=/typescript-4.8.0-insiders.20220721.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/pr-build@4.8.0-pr-49981-17".;

@typescript-bot

Copy link
Copy Markdown
Contributor

Heya Jake Bailey (@jakebailey), I've run the RWC suite on this PR - assuming you're on the TS core team, you can view the resulting diff here.

@typescript-bot

Copy link
Copy Markdown
Contributor

Jake Bailey (@jakebailey)
Great news! no new errors were found between main..refs/pull/49981/merge

@jakebailey

Copy link
Copy Markdown
MemberAuthor

Demo as of this current commit: Playground Link

@jakebailey

Jake Bailey (jakebailey) commented Jul 22, 2022

Copy link
Copy Markdown
MemberAuthor

RE: the RWC tests, I think there might be one error in there that's real, but I'm having trouble understanding what's going on there because it looks like a bunch of unrelated things are showing up in the diff that shouldn't be there if the diff was running on the same version of the test codebases.

The error sort of implies that void should also be considered, though...

@jakebailey
Jake Bailey (jakebailey) marked this pull request as ready for review July 22, 2022 18:28
@typescript-botTypeScript Bot (typescript-bot) added For Milestone Bug PRs that fix a bug with a specific milestone and removed For Uncommitted Bug PR for untriaged, rejected, closed or missing bug labels Jul 22, 2022
@jakebailey

Copy link
Copy Markdown
MemberAuthor

TypeScript Bot (@typescript-bot) perf test this faster

@typescript-bot

TypeScript Bot (typescript-bot) commented Jul 22, 2022

Copy link
Copy Markdown
Contributor

Heya Jake Bailey (@jakebailey), I've started to run the abridged perf test suite on this PR at a817435. You can monitor the build here.

Update: The results are in!

@typescript-bot

Copy link
Copy Markdown
Contributor

Jake Bailey (@jakebailey)
The results of the perf run you requested are in!

Here they are:

Comparison Report - main..49981

Metricmain49981DeltaBestWorst
Angular - node (v14.15.1, x64)
Memory used335,954k (± 0.00%)335,952k (± 0.01%)-2k (- 0.00%)335,900k336,022k
Parse Time2.05s (± 0.52%)2.07s (± 0.48%)+0.01s (+ 0.58%)2.04s2.09s
Bind Time0.89s (± 0.84%)0.90s (± 0.91%)+0.00s (+ 0.45%)0.88s0.92s
Check Time5.81s (± 0.52%)5.83s (± 0.40%)+0.02s (+ 0.34%)5.76s5.87s
Emit Time6.36s (± 0.30%)6.38s (± 0.61%)+0.02s (+ 0.31%)6.29s6.46s
Total Time15.12s (± 0.28%)15.17s (± 0.44%)+0.06s (+ 0.38%)14.98s15.30s
Compiler-Unions - node (v14.15.1, x64)
Memory used193,134k (± 0.02%)193,102k (± 0.01%)-32k (- 0.02%)193,059k193,144k
Parse Time0.85s (± 0.73%)0.85s (± 1.04%)+0.01s (+ 0.59%)0.84s0.88s
Bind Time0.57s (± 0.64%)0.57s (± 0.97%)+0.01s (+ 1.06%)0.56s0.58s
Check Time6.71s (± 0.59%)6.71s (± 0.31%)+0.00s (+ 0.06%)6.66s6.75s
Emit Time2.49s (± 1.02%)2.51s (± 1.37%)+0.02s (+ 0.76%)2.46s2.63s
Total Time10.61s (± 0.41%)10.65s (± 0.45%)+0.04s (+ 0.34%)10.59s10.82s
Monaco - node (v14.15.1, x64)
Memory used325,660k (± 0.00%)325,628k (± 0.01%)-31k (- 0.01%)325,579k325,675k
Parse Time1.58s (± 0.39%)1.58s (± 0.56%)+0.01s (+ 0.38%)1.57s1.61s
Bind Time0.78s (± 0.60%)0.78s (± 0.46%)+0.00s (+ 0.51%)0.78s0.79s
Check Time5.68s (± 0.49%)5.69s (± 0.54%)+0.02s (+ 0.30%)5.64s5.76s
Emit Time3.34s (± 0.47%)3.36s (± 0.66%)+0.01s (+ 0.45%)3.31s3.42s
Total Time11.38s (± 0.22%)11.42s (± 0.43%)+0.04s (+ 0.38%)11.34s11.56s
TFS - node (v14.15.1, x64)
Memory used288,788k (± 0.01%)288,806k (± 0.01%)+18k (+ 0.01%)288,743k288,856k
Parse Time1.32s (± 1.67%)1.34s (± 1.72%)+0.03s (+ 1.97%)1.30s1.41s
Bind Time0.77s (± 4.97%)0.77s (± 4.64%)-0.01s (- 1.16%)0.73s0.86s
Check Time5.35s (± 0.38%)5.37s (± 0.38%)+0.02s (+ 0.36%)5.33s5.42s
Emit Time3.58s (± 1.99%)3.58s (± 2.15%)-0.00s (- 0.00%)3.42s3.71s
Total Time11.02s (± 0.79%)11.05s (± 0.78%)+0.03s (+ 0.25%)10.86s11.19s
material-ui - node (v14.15.1, x64)
Memory used446,695k (± 0.01%)446,605k (± 0.05%)-90k (- 0.02%)445,630k446,780k
Parse Time1.87s (± 0.37%)1.89s (± 0.47%)+0.01s (+ 0.80%)1.87s1.91s
Bind Time0.72s (± 0.80%)0.72s (± 0.92%)-0.00s (- 0.00%)0.71s0.74s
Check Time13.12s (± 0.50%)13.30s (± 0.73%)+0.18s (+ 1.37%)13.04s13.57s
Emit Time0.00s (± 0.00%)0.00s (± 0.00%)0.00s ( NaN%)0.00s0.00s
Total Time15.72s (± 0.46%)15.91s (± 0.64%)+0.20s (+ 1.25%)15.64s16.20s
xstate - node (v14.15.1, x64)
Memory used541,302k (± 0.00%)541,298k (± 0.01%)-4k (- 0.00%)541,241k541,370k
Parse Time2.60s (± 0.40%)2.60s (± 0.64%)+0.00s (+ 0.04%)2.57s2.64s
Bind Time1.17s (± 1.43%)1.14s (± 1.57%)-0.02s (- 1.89%)1.11s1.19s
Check Time1.55s (± 0.53%)1.55s (± 0.49%)+0.01s (+ 0.45%)1.54s1.57s
Emit Time0.07s (± 0.00%)0.07s (± 4.66%)+0.00s (+ 4.29%)0.07s0.08s
Total Time5.38s (± 0.42%)5.37s (± 0.30%)-0.01s (- 0.19%)5.34s5.42s
System
Machine Namets-ci-ubuntu
Platformlinux 4.4.0-210-generic
Architecturex64
Available Memory16 GB
Available Memory15 GB
CPUs4 × Intel(R) Core(TM) i7-4770 CPU @ 3.40GHz
Hosts
  • node (v14.15.1, x64)
Scenarios
  • Angular - node (v14.15.1, x64)
  • Compiler-Unions - node (v14.15.1, x64)
  • Monaco - node (v14.15.1, x64)
  • TFS - node (v14.15.1, x64)
  • material-ui - node (v14.15.1, x64)
  • xstate - node (v14.15.1, x64)
BenchmarkNameIterations
Current4998110
Baselinemain10

Developer Information:

Download Benchmark

Comment on lines +21243 to +21244
function someHas(type: Type, flags: TypeFlags): boolean {
return someType(type, t => !!(t.flags & flags));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels common enough that I would rather us lift it up to someTypeHasFlags

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can do that, yeah, though I think most places just entirely inline it, so I could just do that too.

@jakebailey

Copy link
Copy Markdown
MemberAuthor

#50021 is a more complete fix than mine now, so, closing.

@microsoftMicrosoft (microsoft) locked as resolved and limited conversation to collaborators Oct 22, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Author: TeamFor Milestone BugPRs that fix a bug with a specific milestone

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Inference doesn't find common base type for union with null or undefined - TypeScript 4.8 regression

3 participants

@jakebailey@typescript-bot@DanielRosenwasser