Skip to content

Don't compare "missing" to undefined in compareProperties under exactOptionalPropertyTypes - #61683

Merged
Jake Bailey (jakebailey) merged 2 commits into
microsoft:mainfrom
HansBrende:fix61547
Sep 30, 2025
Merged

Don't compare "missing" to undefined in compareProperties under exactOptionalPropertyTypes#61683
Jake Bailey (jakebailey) merged 2 commits into
microsoft:mainfrom
HansBrende:fix61547

Conversation

@HansBrende

Copy link
Copy Markdown
Contributor

Fixes#61547

I'm aware that the underlying issue is (currently) labeled "not a defect", however, the behavior is undeniably strange, most likely simply overlooked when exactOptionalPropertyTypes was implemented, in my view. Therefore I am opening this PR to demonstrate what an easy fix it is (and that no other tests are broken as a result).

@github-project-automationgithub-project-automationBot moved this to Not started in PR BacklogMay 9, 2025
@typescript-botTypeScript Bot (typescript-bot) added the For Uncommitted Bug PR for untriaged, rejected, closed or missing bug label May 9, 2025
@jakebailey

Copy link
Copy Markdown
Member

TypeScript Bot (@typescript-bot) test it

@typescript-bot

TypeScript Bot (typescript-bot) commented May 9, 2025

Copy link
Copy Markdown
Contributor

Starting jobs; this comment will be updated as builds start and complete.

CommandStatusResults
test top400✅ Started✅ Results
user test this✅ Started✅ Results
run dt✅ Started✅ Results
perf test this faster✅ Started👀 Results

@typescript-bot

Copy link
Copy Markdown
Contributor

Hey Jake Bailey (@jakebailey), the results of running the DT tests are ready.

Everything looks the same!

You can check the log here.

@typescript-bot

Copy link
Copy Markdown
Contributor

Jake Bailey (@jakebailey) Here are the results of running the user tests with tsc comparing main and refs/pull/61683/merge:

Everything looks good!

@HansBrendeHans Brende (HansBrende) changed the title fix 61547Don't compare "missing" to undefined in compareProperties under exactOptionalPropertyTypesMay 9, 2025
@typescript-bot

Copy link
Copy Markdown
Contributor

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

Here they are:

tsc

Comparison Report - baseline..pr
MetricbaselineprDeltaBestWorstp-value
Compiler-Unions - node (v18.15.0, x64)
Errors3434~~~p=1.000 n=6
Symbols62,39062,390~~~p=1.000 n=6
Types50,39550,395~~~p=1.000 n=6
Memory used194,755k (± 1.00%)193,619k (± 0.74%)~192,937k196,535kp=0.230 n=6
Parse Time1.31s (± 0.39%)1.30s (± 0.94%)~1.29s1.32sp=0.241 n=6
Bind Time0.73s0.73s~~~p=1.000 n=6
Check Time9.73s (± 0.39%)9.76s (± 0.54%)~9.68s9.82sp=0.221 n=6
Emit Time2.73s (± 0.50%)2.73s (± 0.67%)~2.71s2.76sp=0.591 n=6
Total Time14.51s (± 0.21%)14.53s (± 0.30%)~14.48s14.59sp=0.376 n=6
angular-1 - node (v18.15.0, x64)
Errors5656~~~p=1.000 n=6
Symbols949,240949,240~~~p=1.000 n=6
Types411,065411,065~~~p=1.000 n=6
Memory used1,225,103k (± 0.00%)1,225,092k (± 0.00%)~1,225,021k1,225,126kp=0.378 n=6
Parse Time6.63s (± 0.95%)6.67s (± 0.84%)~6.56s6.71sp=0.289 n=6
Bind Time1.88s (± 0.43%)1.88s (± 0.40%)~1.87s1.89sp=0.729 n=6
Check Time31.92s (± 0.27%)31.93s (± 0.22%)~31.83s32.00sp=0.936 n=6
Emit Time15.22s (± 0.25%)15.20s (± 0.74%)~15.11s15.42sp=0.127 n=6
Total Time55.66s (± 0.22%)55.68s (± 0.19%)~55.53s55.82sp=0.872 n=6
mui-docs - node (v18.15.0, x64)
Errors00~~~p=1.000 n=6
Symbols2,439,9202,439,920~~~p=1.000 n=6
Types872,553872,553~~~p=1.000 n=6
Memory used2,448,534k (± 0.00%)2,448,463k (± 0.00%)~2,448,390k2,448,583kp=0.066 n=6
Parse Time10.54s (± 0.65%)10.58s (± 0.62%)~10.47s10.66sp=0.377 n=6
Bind Time2.72s (± 0.45%)2.71s (± 1.01%)~2.67s2.75sp=0.462 n=6
Check Time88.08s (± 1.75%)87.44s (± 2.62%)~86.06s92.06sp=0.298 n=6
Emit Time0.37s (± 2.67%)0.37s (± 2.41%)~0.36s0.38sp=0.931 n=6
Total Time101.70s (± 1.54%)101.10s (± 2.27%)~99.84s105.74sp=0.378 n=6
self-build-src - node (v18.15.0, x64)
Errors00~~~p=1.000 n=6
Symbols1,228,2411,228,241~~~p=1.000 n=6
Types267,270267,270~~~p=1.000 n=6
Memory used3,094,833k (± 0.02%)3,095,338k (± 0.02%)~3,094,660k3,096,308kp=0.093 n=6
Parse Time6.72s (± 0.34%)6.70s (± 0.32%)~6.67s6.72sp=0.128 n=6
Bind Time2.13s (± 0.78%)2.16s (± 0.86%)+0.03s (+ 1.56%)2.14s2.18sp=0.030 n=6
Check Time42.79s (± 0.49%)42.88s (± 0.22%)~42.79s43.05sp=0.575 n=6
Emit Time3.50s (± 1.57%)3.42s (± 2.81%)~3.33s3.57sp=0.128 n=6
Total Time55.13s (± 0.43%)55.16s (± 0.16%)~55.01s55.24sp=0.575 n=6
self-build-src-public-api - node (v18.15.0, x64)
Errors00~~~p=1.000 n=6
Symbols1,228,2411,228,241~~~p=1.000 n=6
Types267,270267,270~~~p=1.000 n=6
Memory used2,674,444k (±14.04%)3,038,397k (± 9.78%)~2,431,009k3,161,183kp=0.173 n=6
Parse Time6.87s (± 1.84%)6.95s (± 2.40%)~6.65s7.16sp=0.575 n=6
Bind Time2.21s (± 1.55%)2.15s (± 2.59%)~2.10s2.26sp=0.077 n=6
Check Time42.75s (± 0.50%)42.98s (± 0.34%)~42.79s43.13sp=0.066 n=6
Emit Time3.56s (± 2.74%)3.48s (± 2.92%)~3.37s3.63sp=0.378 n=6
Total Time55.39s (± 0.72%)55.54s (± 0.60%)~55.13s56.02sp=0.471 n=6
self-compiler - node (v18.15.0, x64)
Errors00~~~p=1.000 n=6
Symbols263,442263,442~~~p=1.000 n=6
Types107,097107,097~~~p=1.000 n=6
Memory used441,827k (± 0.01%)441,786k (± 0.02%)~441,682k441,930kp=0.298 n=6
Parse Time3.56s (± 1.22%)3.56s (± 0.73%)~3.54s3.61sp=0.871 n=6
Bind Time1.33s (± 0.95%)1.33s (± 1.00%)~1.31s1.35sp=0.788 n=6
Check Time19.04s (± 0.33%)19.06s (± 0.17%)~19.02s19.12sp=0.124 n=6
Emit Time1.54s (± 0.79%)1.52s (± 0.59%)-0.02s (- 1.08%)1.51s1.53sp=0.039 n=6
Total Time25.46s (± 0.30%)25.47s (± 0.14%)~25.44s25.53sp=0.936 n=6
ts-pre-modules - node (v18.15.0, x64)
Errors7171~~~p=1.000 n=6
Symbols225,981225,981~~~p=1.000 n=6
Types94,35694,356~~~p=1.000 n=6
Memory used371,270k (± 0.01%)371,373k (± 0.05%)~371,210k371,633kp=0.689 n=6
Parse Time3.58s (± 0.86%)3.59s (± 0.95%)~3.55s3.63sp=0.629 n=6
Bind Time1.96s (± 1.04%)1.97s (± 0.75%)~1.95s1.99sp=0.370 n=6
Check Time20.50s (± 0.40%)20.46s (± 0.11%)~20.43s20.49sp=0.261 n=6
Emit Time0.00s0.00s~~~p=1.000 n=6
Total Time26.04s (± 0.31%)26.01s (± 0.23%)~25.94s26.08sp=0.629 n=6
vscode - node (v18.15.0, x64)
Errors5151~~~p=1.000 n=6
Symbols3,427,9723,427,972~~~p=1.000 n=6
Types1,156,1701,156,170~~~p=1.000 n=6
Memory used3,477,054k (± 0.01%)3,477,182k (± 0.00%)~3,477,048k3,477,353kp=0.230 n=6
Parse Time18.03s (± 0.35%)18.02s (± 0.34%)~17.92s18.09sp=0.688 n=6
Bind Time5.78s (± 0.37%)5.77s (± 0.40%)~5.74s5.80sp=0.413 n=6
Check Time116.14s (± 2.64%)114.09s (± 2.69%)~112.29s120.32sp=0.066 n=6
Emit Time37.01s (± 2.21%)36.28s (± 0.37%)~36.07s36.46sp=0.261 n=6
Total Time176.97s (± 2.15%)174.17s (± 1.75%)~172.47s180.36sp=0.066 n=6
webpack - node (v18.15.0, x64)
Errors22~~~p=1.000 n=6
Symbols317,848317,848~~~p=1.000 n=6
Types140,485140,485~~~p=1.000 n=6
Memory used473,085k (± 0.01%)473,071k (± 0.02%)~472,881k473,168kp=0.936 n=6
Parse Time4.12s (± 1.05%)4.14s (± 0.91%)~4.08s4.19sp=0.336 n=6
Bind Time1.82s (± 1.30%)1.83s (± 1.58%)~1.79s1.86sp=0.936 n=6
Check Time21.00s (± 0.39%)20.89s (± 0.33%)~20.81s20.98sp=0.065 n=6
Emit Time0.00s0.00s~~~p=1.000 n=6
Total Time26.95s (± 0.38%)26.86s (± 0.48%)~26.71s26.98sp=0.199 n=6
xstate-main - node (v18.15.0, x64)
Errors55~~~p=1.000 n=6
Symbols570,733570,733~~~p=1.000 n=6
Types191,446191,446~~~p=1.000 n=6
Memory used501,130k (± 0.04%)501,354k (± 0.02%)~501,253k501,465kp=0.066 n=6
Parse Time4.33s (± 0.68%)4.32s (± 0.54%)~4.28s4.35sp=0.372 n=6
Bind Time1.53s (± 1.91%)1.54s (± 1.06%)~1.53s1.57sp=0.805 n=6
Check Time25.97s (± 3.61%)25.01s (± 0.47%)~24.80s25.13sp=0.230 n=6
Emit Time0.00s0.00s (±244.70%)~0.00s0.01sp=0.405 n=6
Total Time31.83s (± 2.82%)30.87s (± 0.36%)~30.66s30.96sp=0.229 n=6
System info unknown
Hosts
  • node (v18.15.0, x64)
Scenarios
  • Compiler-Unions - node (v18.15.0, x64)
  • angular-1 - node (v18.15.0, x64)
  • mui-docs - node (v18.15.0, x64)
  • self-build-src - node (v18.15.0, x64)
  • self-build-src-public-api - node (v18.15.0, x64)
  • self-compiler - node (v18.15.0, x64)
  • ts-pre-modules - node (v18.15.0, x64)
  • vscode - node (v18.15.0, x64)
  • webpack - node (v18.15.0, x64)
  • xstate-main - node (v18.15.0, x64)
BenchmarkNameIterations
Currentpr6
Baselinebaseline6

Developer Information:

Download Benchmarks

@typescript-bot

Copy link
Copy Markdown
Contributor

Jake Bailey (@jakebailey) Here are the results of running the top 400 repos with tsc comparing main and refs/pull/61683/merge:

Everything looks good!

@HansBrende

Hans Brende (HansBrende) commented May 20, 2025

Copy link
Copy Markdown
ContributorAuthor

Jake Bailey (@jakebailey) given the likelihood of this being an oversight when exactOptionalPropertyTypes was implemented and the simplicity of the fix, do you see it likely we'd be able to remove the "not a defect" label from the original issue (and hopefully add it to the backlog so that this PR can be reviewed)?

As you saw, I was hoping to get confirmation from the original author Anders Hejlsberg (@ahejlsberg) that it was simply a case of "missed a spot" when changing getTypeOfSymbol to getNonMissingTypeOfSymbol, but I haven't heard anything back as of yet.

@jakebailey

Copy link
Copy Markdown
Member

TypeScript Bot (@typescript-bot) pack this

@typescript-bot

TypeScript Bot (typescript-bot) commented Jun 9, 2025

Copy link
Copy Markdown
Contributor

Starting jobs; this comment will be updated as builds start and complete.

CommandStatusResults
pack this✅ Started✅ Results

@typescript-bot

TypeScript Bot (typescript-bot) commented Jun 9, 2025

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/165319/artifacts?artifactName=tgz&fileId=4F665885689AA916692B97D478FF2A8630D9C111C45A58BF75E4C117B832487302&fileName=/typescript-5.9.0-insiders.20250609.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@5.9.0-pr-61683-9".;

@jakebailey

Jake Bailey (jakebailey) commented Jun 9, 2025

Copy link
Copy Markdown
Member

Testing #61547 with Playground Link, are these errors right? The first one is the reported one, sure, but it's seemingly missing two errors.

I think this PR should be encoding all of the test provided in the issue in any case. But, it's not clear if the new behavior is correct either.

@HansBrende

Hans Brende (HansBrende) commented Jun 9, 2025

Copy link
Copy Markdown
ContributorAuthor

Jake Bailey (@jakebailey) hi! Can you explain what you mean by "missing two errors"? Not sure I follow. The issue is complaining that the Assert<Equal<T1, T2>> is not considered an error in v5.8.3, but it should be considered an error. (While all of the assertions that follow this are correct and their behavior should not be changed--these code paths are already heavily tested, hence why I did not include additional tests for them.)

@jakebailey

Copy link
Copy Markdown
Member

The example seemingly implies that under exactOptionalPropertyTypes that all of those assertions should pass, except that the first one doesn't. But with this PR, the first is eliminated but the next two now fail.

@jakebailey

Copy link
Copy Markdown
Member

Hm, I might have some wires crossed in my explanation given there are 2 playgrounds, 2 settings, and 4 assertions (sorry, I need to explain it better), but the gist is that it seems like this PR introduces errors into one of the variants that weren't there previously in 5.8.

@HansBrende

Copy link
Copy Markdown
ContributorAuthor

The example seemingly implies that under exactOptionalPropertyTypes that all of those assertions should pass, except that the first one doesn't.

Jake Bailey (@jakebailey) I can see how the issue could be misconstrued, however, simply changing the environment to 5.8.3 shows that the first assertion does pass currently.

The issue was raised to highlight that the first assertion should fail but currently passes. This is the reason for the "❌" in the comment above just that one assertion: identifying that this current behavior is incorrect.

The subsequent assertions are only provided to show that under exactOptionalPropertyTypes, T2 is not assignable to T1: evidence that T2 & T1 should not be considered identical types, and therefore that the first assertion is incorrectly passing.

with this PR, the first is eliminated but the next two now fail

I'm still not seeing these 2 failures you're mentioning... opening your playground link gives me what I would expect:

Screenshot 2025-06-09 at 8 00 52 PM

it seems like this PR introduces errors into one of the variants that weren't there previously in 5.8.

Yes, this is absolutely correct and very much intended! The whole point of the issue is to do exactly that, to introduce one error into the first assertion. (If there were any other assertions besides the first that became an error, that would definitely be a bug in my implementation, but I don't see how that could be possible because I haven't touched those code paths.)

@jakebailey

Copy link
Copy Markdown
Member

Let me go through the matrix:

VersionexactOptionalPropertyTypes=falseexactOptionalPropertyTypes=true
5.8.3imageimage
This PRimageimage

I think I was just mistaken. exactOptionalPropertyTypes=false is unaffected.

@HansBrende

Copy link
Copy Markdown
ContributorAuthor

Jake Bailey (@jakebailey) correct, because getNonMissingTypeOfSymbol is semantically identical to getTypeOfSymbol under exactOptionalPropertyTypes=false, so this PR is a no-op in that case.

Let me know if you need anything else from me! 😃

@HansBrende

Copy link
Copy Markdown
ContributorAuthor

Jake Bailey (@jakebailey) anything else you need from me on this and/or anything blocking this PR being accepted? Should I click "Update branch" or does that not matter?

@jakebailey

Copy link
Copy Markdown
Member

Nothing; we are in a code freeze until we open the tree for 6.0.

@HansBrende

Copy link
Copy Markdown
ContributorAuthor

Jake Bailey (@jakebailey) follow-up: I see that typescript has been publishing "6.0.0-dev" versions on npm for a while now, does that imply that the tree has opened for 6.0 and the code freeze has ended or did you mean something else?

@jakebailey

Copy link
Copy Markdown
Member

Yes, that's correct.

@jakebailey

Copy link
Copy Markdown
Member

This PR needs a merge from main to be unblocked.

@HansBrende

Copy link
Copy Markdown
ContributorAuthor

Jake Bailey (@jakebailey) done!

@HansBrende

Copy link
Copy Markdown
ContributorAuthor

Jake Bailey (@jakebailey) I noticed the branch is already out of date again: do you need me to keep merging from main every time I see it goes out of date to remain unblocked? Happy to do so if that's the case.

@jakebailey

Copy link
Copy Markdown
Member

Nope, I asked for a merge because we added some new required CI checks that weren't present on the branch the last time CI ran.

@github-project-automationgithub-project-automationBot moved this from Not started to Needs merge in PR BacklogSep 30, 2025
@jakebailey
Jake Bailey (jakebailey) merged commit 31a0ead into microsoft:mainSep 30, 2025
33 checks passed
@github-project-automationgithub-project-automationBot moved this from Needs merge to Done in PR BacklogSep 30, 2025
Eran Hirsch (eranhirsch) added a commit to remeda/remeda that referenced this pull request Jan 2, 2026
…pertyTypes` is enabled (#1246)
Fixing issues with optional tuple properties following changes coming
soon to TypeScript discovered by the canary tests:
https://github.com/remeda/remeda/actions/runs/20653076637.
Specifically following this change:
microsoft/TypeScript#61683
@microsoftMicrosoft (microsoft) locked as resolved and limited conversation to collaborators Apr 2, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

For Uncommitted BugPR for untriaged, rejected, closed or missing bug

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

exactOptionalPropertyTypes: strict type equality is too lenient

5 participants

@HansBrende@jakebailey@typescript-bot@DanielRosenwasser@andrewbranch