Skip to content

Conversation

@ahejlsberg
Copy link
Member

@ahejlsbergahejlsberg commented May 7, 2025

This PR fixes two issues leading to type variable leaks and cache inconsistencies.

The first issue, reported in #59937, relates to instantiations of single-signature types with inferred type parameters sometimes leaking into other types because of omitted information in cache keys. The fix to this issue is to properly include the base type mapper when computing cache keys.

The second issue, reported in #61667, relates to circular inferences, i.e. situations where inferences reference type parameters for which the inferences are being made. This was reported fixed by #57403, but the situation still persists as demonstrated by #61667.

Our type inference infrastructure makes a core assumption that inferences aren't circular, and while #57403 manages to permit them in certain cases, it is unfortunately not a general solution. For that reason, this PR reverts #57403 and instead puts in place logic that ensures outer type parameters in contextual types are instantiated (possibly just to their constraints) before inferences are made to return types of inner function calls. Specifically, in this code

declarefunctioncall<A,R>(obj: {x: (a: A)=>R},arg: A): Rdeclarefunctionwrap<X>(x: X): {x: X}declarefunctionid<T>(x: T): T;constx=call(wrap(id),1);// Previously 'A', now 'unknown'

the result of wrap(id) has type {x: <T>(x: T) => T } and is contextually typed by {x: (a: A) => R }. Previously, we'd infer (x: A) => A as the type argument for X in the call to wrap, propagate that into the {x: (x: A) => A } result type, and then infer from that result type to {x: (a: A) => R }, producing the inference A for A. Which doesn't make sense (or at least would require a more sophisticated unification algorithm to reason about). With this PR, we ensure that the contextual type for the wrap(id) call is instantiated to be free of references to outer type parameters. This means that the contextual type is {x: (x: unknown) => unknown } and thus we make low priority inferences of unknown for A and R. We then subsequently make a better inference of 1 for A.

It would be nice if the example above would manage to propagate the inference of 1 for A all the way through to R, but we lack the machinery to do so (because we don't perform full unification). We are equipped to do it for "unwrapped" functions like <T>(x: T) => T, but not for generic functions nested in object types. It's simply a design limitation.

Because this PR reverts #57403, it is technically a breaking change. But it wasn't working right in the first place.

Fixes#59937.
Fixes#61667.

CopilotAI review requested due to automatic review settings May 7, 2025 22:34
@github-project-automationgithub-project-automationbot moved this to Not started in PR BacklogMay 7, 2025
@typescript-bot
Copy link
Collaborator

Looks like you're introducing a change to the public API surface area. If this includes breaking changes, please document them on our wiki's API Breaking Changes page.

Also, please make sure @DanielRosenwasser and @RyanCavanaugh are aware of the changes, just as a heads up.

Copy link
Contributor

CopilotAI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR fixes two long‐standing issues—type variable leaks and cache inconsistencies—in our type inference system by properly incorporating the base type mapper into cache key computations and ensuring that outer type parameters in contextual types are instantiated before inference. In doing so, it reverts a previous change (#57403) and updates several tests and baseline outputs to reflect the correct, more conservative inference behavior.

  • Properly include the base type mapper when computing cache keys
  • Instantiate outer type parameters to avoid circular inferences during return type inference
  • Update test cases and baselines to match the new behavior

Reviewed Changes

Copilot reviewed 24 out of 24 changed files in this pull request and generated no comments.

FileDescription
tests/cases/compiler/*.tsNew tests and example functions (e.g. withP3) to confirm that generic call inference behaves as expected.
tests/baselines/reference/*Baseline outputs have been updated (instantiation counts, inferred types, and symbols) to reflect the fixes.
src/compiler/types.tsRemoved duplicate flag and deprecated interface definitions for SingleSignatureType to prevent leaks.
src/compiler/checker.tsRefactored signature instantiation logic (e.g. removal of unused helper functions, introduction of createOuterReturnMapper) to improve cache consistency and type inference accuracy.
Comments suppressed due to low confidence (2)

src/compiler/checker.ts:16310

  • [nitpick] Changing the parameter type from 'readonly Type[]' to 'Type[]' in getSignatureInstantiation improves mutability control and clarity; ensure that all relevant usages are consistent with this change.
function getSignatureInstantiation(signature: Signature, typeArguments: readonly Type[] | undefined, isJavascript: boolean, inferredTypeParameters?: readonly TypeParameter[]): Signature{

src/compiler/types.ts:6495

  • The duplication of the SingleSignatureType flag has been removed and defined only once. Verify that removing the previously stored 'outerTypeParameters' in SingleSignatureType does not affect dependent logic.
SingleSignatureType = 1 << 27, // A single signature type extracted from a potentially broader type 

@ahejlsberg
Copy link
MemberAuthor

@typescript-bot test it

@typescript-bot
Copy link
Collaborator

typescript-bot commented May 7, 2025

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
Collaborator

@ahejlsberg Here are the results of running the user tests with tsc comparing main and refs/pull/61668/merge:

Everything looks good!

@typescript-bot
Copy link
Collaborator

Hey @ahejlsberg, the results of running the DT tests are ready.

Everything looks the same!

You can check the log here.

@typescript-bot
Copy link
Collaborator

@ahejlsberg
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,444+54 (+ 0.09%)~~p=0.001 n=6
Types50,39550,418+23 (+ 0.05%)~~p=0.001 n=6
Memory used195,407k (± 0.89%)196,002k (± 0.73%)~193,094k196,681kp=0.230 n=6
Parse Time1.61s (± 0.61%)1.59s (± 2.34%)~1.53s1.64sp=0.368 n=6
Bind Time0.88s (± 1.12%)0.89s (± 1.84%)~0.87s0.91sp=0.402 n=6
Check Time11.78s (± 0.44%)11.76s (± 0.68%)~11.69s11.91sp=0.373 n=6
Emit Time3.34s (± 3.53%)3.34s (± 2.92%)~3.25s3.52sp=1.000 n=6
Total Time17.61s (± 0.92%)17.58s (± 0.74%)~17.45s17.79sp=0.748 n=6
angular-1 - node (v18.15.0, x64)
Errors5656~~~p=1.000 n=6
Symbols949,240948,690-550 (- 0.06%)~~p=0.001 n=6
Types411,065410,866-199 (- 0.05%)~~p=0.001 n=6
Memory used1,225,110k (± 0.00%)1,224,520k (± 0.01%)-589k (- 0.05%)1,224,469k1,224,652kp=0.005 n=6
Parse Time6.63s (± 0.72%)6.65s (± 0.72%)~6.55s6.68sp=0.629 n=6
Bind Time1.88s (± 0.27%)1.89s (± 0.55%)~1.87s1.90sp=0.437 n=6
Check Time31.96s (± 0.34%)31.85s (± 0.56%)~31.62s32.13sp=0.229 n=6
Emit Time15.18s (± 0.63%)15.22s (± 0.43%)~15.12s15.31sp=0.423 n=6
Total Time55.65s (± 0.15%)55.60s (± 0.38%)~55.30s55.88sp=1.000 n=6
mui-docs - node (v18.15.0, x64)
Errors00~~~p=1.000 n=6
Symbols2,439,9292,437,696-2,233 (- 0.09%)~~p=0.001 n=6
Types872,556872,504-52 (- 0.01%)~~p=0.001 n=6
Memory used2,448,492k (± 0.00%)2,448,391k (± 0.00%)~2,448,331k2,448,454kp=0.066 n=6
Parse Time10.54s (± 0.33%)10.55s (± 0.16%)~10.53s10.57sp=0.373 n=6
Bind Time2.68s (± 0.60%)2.71s (± 1.22%)~2.67s2.75sp=0.145 n=6
Check Time87.13s (± 1.38%)87.56s (± 1.48%)~86.27s88.85sp=0.298 n=6
Emit Time0.37s (± 2.81%)0.37s (± 2.41%)~0.36s0.38sp=0.673 n=6
Total Time100.72s (± 1.18%)101.17s (± 1.30%)~99.88s102.53sp=0.336 n=6
self-build-src - node (v18.15.0, x64)
Errors00~~~p=1.000 n=6
Symbols1,228,0521,226,347-1,705 (- 0.14%)~~p=0.001 n=6
Types267,262267,149-113 (- 0.04%)~~p=0.001 n=6
Memory used2,360,718k (± 0.03%)2,359,965k (± 0.03%)~2,359,396k2,361,052kp=0.093 n=6
Parse Time5.22s (± 1.28%)5.22s (± 0.94%)~5.16s5.28sp=1.000 n=6
Bind Time1.81s (± 0.46%)1.80s (± 0.96%)~1.77s1.82sp=0.503 n=6
Check Time35.30s (± 0.19%)34.95s (± 0.26%)-0.35s (- 0.99%)34.81s35.04sp=0.005 n=6
Emit Time2.99s (± 0.81%)2.97s (± 0.87%)~2.95s3.01sp=0.517 n=6
Total Time45.30s (± 0.13%)44.94s (± 0.21%)-0.36s (- 0.80%)44.83s45.11sp=0.005 n=6
self-build-src-public-api - node (v18.15.0, x64)
Errors00~~~p=1.000 n=6
Symbols1,228,0521,226,347-1,705 (- 0.14%)~~p=0.001 n=6
Types267,262267,149-113 (- 0.04%)~~p=0.001 n=6
Memory used2,794,398k (±14.25%)3,035,731k (± 9.78%)~2,428,884k3,157,660kp=0.936 n=6
Parse Time6.87s (± 1.71%)6.90s (± 1.05%)~6.78s6.98sp=0.575 n=6
Bind Time2.16s (± 1.05%)2.18s (± 1.80%)~2.12s2.22sp=0.421 n=6
Check Time42.90s (± 0.71%)42.69s (± 0.34%)~42.43s42.81sp=0.378 n=6
Emit Time3.59s (± 2.98%)3.60s (± 1.42%)~3.54s3.68sp=0.748 n=6
Total Time55.51s (± 0.86%)55.38s (± 0.47%)~54.95s55.63sp=0.810 n=6
self-compiler - node (v18.15.0, x64)
Errors00~~~p=1.000 n=6
Symbols263,419262,452-967 (- 0.37%)~~p=0.001 n=6
Types107,098107,012-86 (- 0.08%)~~p=0.001 n=6
Memory used441,743k (± 0.01%)441,258k (± 0.01%)-485k (- 0.11%)441,178k441,338kp=0.005 n=6
Parse Time4.36s (± 0.60%)4.39s (± 0.75%)~4.36s4.45sp=0.198 n=6
Bind Time1.64s (± 1.08%)1.63s (± 0.55%)~1.62s1.64sp=0.557 n=6
Check Time23.60s (± 0.33%)23.24s (± 0.29%)-0.36s (- 1.53%)23.13s23.31sp=0.005 n=6
Emit Time1.92s (± 0.72%)1.90s (± 1.05%)~1.89s1.94sp=0.084 n=6
Total Time31.51s (± 0.31%)31.16s (± 0.20%)-0.35s (- 1.11%)31.06s31.20sp=0.005 n=6
ts-pre-modules - node (v18.15.0, x64)
Errors7171~~~p=1.000 n=6
Symbols225,981225,347-634 (- 0.28%)~~p=0.001 n=6
Types94,35694,289-67 (- 0.07%)~~p=0.001 n=6
Memory used371,383k (± 0.04%)371,081k (± 0.04%)-302k (- 0.08%)370,964k371,384kp=0.031 n=6
Parse Time2.90s (± 0.94%)2.90s (± 0.87%)~2.86s2.92sp=0.803 n=6
Bind Time1.60s (± 1.42%)1.60s (± 1.15%)~1.58s1.62sp=1.000 n=6
Check Time16.54s (± 0.19%)16.23s (± 0.21%)-0.31s (- 1.87%)16.19s16.29sp=0.005 n=6
Emit Time0.00s0.00s~~~p=1.000 n=6
Total Time21.04s (± 0.31%)20.73s (± 0.17%)-0.31s (- 1.46%)20.68s20.78sp=0.005 n=6
vscode - node (v18.15.0, x64)
Errors5151~~~p=1.000 n=6
Symbols3,419,9023,419,526-376 (- 0.01%)~~p=0.001 n=6
Types1,154,0161,153,443-573 (- 0.05%)~~p=0.001 n=6
Memory used3,472,233k (± 0.01%)3,469,063k (± 0.01%)-3,171k (- 0.09%)3,468,667k3,469,373kp=0.005 n=6
Parse Time18.22s (± 0.46%)18.25s (± 0.67%)~18.14s18.48sp=0.809 n=6
Bind Time5.79s (± 0.66%)5.77s (± 0.62%)~5.72s5.83sp=0.260 n=6
Check Time116.08s (± 3.18%)113.61s (± 2.27%)~111.83s118.40sp=0.336 n=6
Emit Time37.25s (± 2.27%)36.53s (± 1.84%)~36.05s37.87sp=0.230 n=6
Total Time177.35s (± 2.50%)174.17s (± 1.84%)~171.88s180.35sp=0.378 n=6
webpack - node (v18.15.0, x64)
Errors22~~~p=1.000 n=6
Symbols317,848317,740-108 (- 0.03%)~~p=0.001 n=6
Types140,485140,433-52 (- 0.04%)~~p=0.001 n=6
Memory used472,966k (± 0.01%)472,774k (± 0.01%)-191k (- 0.04%)472,693k472,846kp=0.005 n=6
Parse Time3.36s (± 0.85%)3.37s (± 0.93%)~3.34s3.43sp=0.405 n=6
Bind Time1.51s (± 0.27%)1.51s (± 0.65%)~1.49s1.52sp=0.673 n=6
Check Time17.48s (± 0.11%)17.44s (± 0.30%)~17.36s17.49sp=0.293 n=6
Emit Time0.00s0.00s~~~p=1.000 n=6
Total Time22.35s (± 0.09%)22.32s (± 0.31%)~22.23s22.42sp=0.335 n=6
xstate-main - node (v18.15.0, x64)
Errors55~~~p=1.000 n=6
Symbols570,733567,169-3,564 (- 0.62%)~~p=0.001 n=6
Types191,446190,593-853 (- 0.45%)~~p=0.001 n=6
Memory used501,289k (± 0.03%)499,538k (± 0.01%)-1,751k (- 0.35%)499,454k499,591kp=0.005 n=6
Parse Time3.46s (± 0.42%)3.45s (± 0.87%)~3.42s3.50sp=0.290 n=6
Bind Time1.22s (± 1.85%)1.22s (± 0.68%)~1.21s1.23sp=0.138 n=6
Check Time20.40s (± 2.94%)20.11s (± 0.55%)~19.94s20.27sp=0.127 n=6
Emit Time0.00s0.00s~~~p=1.000 n=6
Total Time25.07s (± 2.40%)24.78s (± 0.53%)~24.59s24.97sp=0.415 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
Collaborator

@ahejlsberg Here are the results of running the top 400 repos with tsc comparing main and refs/pull/61668/merge:

Something interesting changed - please have a look.

Details

apollographql/apollo-client

3 of 13 projects failed to build with the old tsc and were ignored

eslint-local-rules/tsconfig.json

@ahejlsberg
Copy link
MemberAuthor

@typescript-bot test it

@typescript-bot
Copy link
Collaborator

typescript-bot commented May 8, 2025

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
Collaborator

Hey @ahejlsberg, the results of running the DT tests are ready.

Everything looks the same!

You can check the log here.

@typescript-bot
Copy link
Collaborator

@ahejlsberg Here are the results of running the user tests with tsc comparing main and refs/pull/61668/merge:

Something interesting changed - please have a look.

Details

fp-ts

tsconfig.json

  • [NEW] error TS2345: Argument of type 'Option<[Option<number>, Option<number>, Option<number>]>' is not assignable to parameter of type 'Option<NonEmptyArray<Some<number>>>'.
  • [NEW] error TS2345: Argument of type 'Option<[Option<number>, Option<number>]>' is not assignable to parameter of type 'Option<NonEmptyArray<Some<number>>>'.
  • [NEW] error TS2345: Argument of type '<C>(bc: readonly [C, 1]) => readonly [C, string]' is not assignable to parameter of type '(a: readonly [true, 2]) => readonly [true, string]'.

tsconfig.eslint.json

  • [NEW] error TS2345: Argument of type 'Option<[Option<number>, Option<number>, Option<number>]>' is not assignable to parameter of type 'Option<NonEmptyArray<Some<number>>>'.
  • [NEW] error TS2345: Argument of type 'Option<[Option<number>, Option<number>]>' is not assignable to parameter of type 'Option<NonEmptyArray<Some<number>>>'.
  • [NEW] error TS2345: Argument of type '<C>(bc: readonly [C, 1]) => readonly [C, string]' is not assignable to parameter of type '(a: readonly [true, 2]) => readonly [true, string]'.

@typescript-bot
Copy link
Collaborator

@ahejlsberg
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,370-20 (- 0.03%)~~p=0.001 n=6
Types50,39550,386-9 (- 0.02%)~~p=0.001 n=6
Memory used192,980k (± 0.01%)194,205k (± 0.95%)~192,905k196,581kp=1.000 n=6
Parse Time1.31s (± 0.84%)1.31s (± 0.39%)~1.30s1.31sp=0.324 n=6
Bind Time0.73s0.73s~~~p=1.000 n=6
Check Time9.74s (± 0.36%)9.72s (± 0.53%)~9.63s9.77sp=1.000 n=6
Emit Time2.73s (± 0.89%)2.73s (± 0.89%)~2.71s2.77sp=1.000 n=6
Total Time14.51s (± 0.28%)14.49s (± 0.39%)~14.39s14.56sp=0.685 n=6
angular-1 - node (v18.15.0, x64)
Errors5656~~~p=1.000 n=6
Symbols949,240948,689-551 (- 0.06%)~~p=0.001 n=6
Types411,065410,864-201 (- 0.05%)~~p=0.001 n=6
Memory used1,225,104k (± 0.00%)1,224,498k (± 0.01%)-606k (- 0.05%)1,224,409k1,224,589kp=0.005 n=6
Parse Time6.64s (± 0.68%)6.64s (± 0.76%)~6.57s6.71sp=1.000 n=6
Bind Time1.89s (± 0.40%)1.88s (± 0.27%)~1.88s1.89sp=0.069 n=6
Check Time31.99s (± 0.35%)31.70s (± 0.40%)-0.28s (- 0.89%)31.60s31.95sp=0.013 n=6
Emit Time15.23s (± 0.43%)15.21s (± 0.35%)~15.13s15.28sp=0.630 n=6
Total Time55.76s (± 0.18%)55.44s (± 0.12%)-0.32s (- 0.57%)55.36s55.54sp=0.005 n=6
mui-docs - node (v18.15.0, x64)
Errors00~~~p=1.000 n=6
Symbols2,439,9292,437,696-2,233 (- 0.09%)~~p=0.001 n=6
Types872,556872,504-52 (- 0.01%)~~p=0.001 n=6
Memory used2,448,236k (± 0.00%)2,448,075k (± 0.00%)-161k (- 0.01%)2,448,050k2,448,124kp=0.005 n=6
Parse Time8.74s (± 0.29%)8.74s (± 0.60%)~8.70s8.84sp=0.686 n=6
Bind Time2.21s (± 0.60%)2.22s (± 0.62%)~2.19s2.23sp=0.216 n=6
Check Time72.46s (± 0.46%)72.38s (± 0.38%)~72.09s72.65sp=0.810 n=6
Emit Time0.30s (± 1.70%)0.30s (± 2.49%)~0.29s0.31sp=0.784 n=6
Total Time83.72s (± 0.41%)83.64s (± 0.29%)~83.34s83.88sp=0.688 n=6
self-build-src - node (v18.15.0, x64)
Errors00~~~p=1.000 n=6
Symbols1,228,0521,226,274-1,778 (- 0.14%)~~p=0.001 n=6
Types267,262267,111-151 (- 0.06%)~~p=0.001 n=6
Memory used2,360,832k (± 0.02%)2,360,123k (± 0.01%)-710k (- 0.03%)2,359,794k2,360,420kp=0.013 n=6
Parse Time5.22s (± 0.89%)5.23s (± 1.28%)~5.13s5.32sp=0.521 n=6
Bind Time1.80s (± 1.05%)1.80s (± 0.76%)~1.78s1.82sp=0.935 n=6
Check Time35.43s (± 0.39%)35.14s (± 0.39%)-0.29s (- 0.82%)34.97s35.29sp=0.020 n=6
Emit Time2.99s (± 0.70%)3.03s (± 0.99%)~2.99s3.07sp=0.092 n=6
Total Time45.44s (± 0.27%)45.20s (± 0.24%)-0.24s (- 0.53%)45.09s45.35sp=0.013 n=6
self-build-src-public-api - node (v18.15.0, x64)
Errors00~~~p=1.000 n=6
Symbols1,228,0521,226,274-1,778 (- 0.14%)~~p=0.001 n=6
Types267,262267,111-151 (- 0.06%)~~p=0.001 n=6
Memory used2,916,430k (±12.89%)2,915,467k (±12.83%)~2,430,145k3,158,297kp=0.298 n=6
Parse Time6.92s (± 1.43%)6.91s (± 1.68%)~6.77s7.02sp=0.872 n=6
Bind Time2.20s (± 1.10%)2.20s (± 1.17%)~2.16s2.24sp=0.810 n=6
Check Time42.86s (± 0.54%)42.52s (± 0.60%)~42.07s42.73sp=0.066 n=6
Emit Time3.54s (± 1.57%)3.50s (± 2.03%)~3.44s3.62sp=0.172 n=6
Total Time55.53s (± 0.66%)55.14s (± 0.72%)~54.47s55.50sp=0.173 n=6
self-compiler - node (v18.15.0, x64)
Errors00~~~p=1.000 n=6
Symbols263,419262,370-1,049 (- 0.40%)~~p=0.001 n=6
Types107,098106,977-121 (- 0.11%)~~p=0.001 n=6
Memory used441,760k (± 0.03%)441,354k (± 0.02%)-407k (- 0.09%)441,220k441,417kp=0.005 n=6
Parse Time3.58s (± 1.04%)3.56s (± 1.00%)~3.49s3.59sp=0.421 n=6
Bind Time1.32s (± 0.62%)1.33s (± 0.79%)~1.31s1.34sp=0.181 n=6
Check Time19.03s (± 0.56%)18.81s (± 0.45%)-0.21s (- 1.12%)18.73s18.97sp=0.020 n=6
Emit Time1.53s (± 1.47%)1.54s (± 0.90%)~1.52s1.55sp=0.935 n=6
Total Time25.45s (± 0.34%)25.22s (± 0.49%)-0.23s (- 0.89%)25.08s25.43sp=0.016 n=6
ts-pre-modules - node (v18.15.0, x64)
Errors7171~~~p=1.000 n=6
Symbols225,981225,327-654 (- 0.29%)~~p=0.001 n=6
Types94,35694,286-70 (- 0.07%)~~p=0.001 n=6
Memory used371,324k (± 0.05%)371,021k (± 0.00%)-304k (- 0.08%)371,004k371,052kp=0.005 n=6
Parse Time2.91s (± 1.33%)2.89s (± 0.52%)~2.88s2.91sp=0.144 n=6
Bind Time1.60s (± 1.02%)1.61s (± 1.47%)~1.59s1.64sp=0.370 n=6
Check Time16.55s (± 0.55%)16.29s (± 0.35%)-0.26s (- 1.58%)16.20s16.37sp=0.005 n=6
Emit Time0.00s (±244.70%)0.00s (±244.70%)~0.00s0.01sp=1.000 n=6
Total Time21.06s (± 0.51%)20.79s (± 0.33%)-0.27s (- 1.27%)20.70s20.90sp=0.005 n=6
vscode - node (v18.15.0, x64)
Errors5151~~~p=1.000 n=6
Symbols3,420,2383,417,911-2,327 (- 0.07%)~~p=0.001 n=6
Types1,153,8951,153,270-625 (- 0.05%)~~p=0.001 n=6
Memory used3,471,974k (± 0.00%)3,468,274k (± 0.00%)-3,700k (- 0.11%)3,468,154k3,468,426kp=0.005 n=6
Parse Time14.65s (± 0.52%)14.79s (± 2.83%)~14.50s15.63sp=0.936 n=6
Bind Time4.71s (± 0.55%)4.72s (± 0.97%)~4.66s4.77sp=0.936 n=6
Check Time93.20s (± 1.62%)95.02s (± 3.35%)~91.47s99.27sp=0.471 n=6
Emit Time30.46s (± 1.67%)30.24s (± 2.77%)~29.49s31.57sp=0.378 n=6
Total Time143.03s (± 1.23%)144.77s (± 2.58%)~140.22s150.23sp=0.575 n=6
webpack - node (v18.15.0, x64)
Errors22~~~p=1.000 n=6
Symbols317,848317,740-108 (- 0.03%)~~p=0.001 n=6
Types140,485140,433-52 (- 0.04%)~~p=0.001 n=6
Memory used473,156k (± 0.02%)472,831k (± 0.02%)-325k (- 0.07%)472,612k472,908kp=0.005 n=6
Parse Time5.17s (± 0.85%)5.14s (± 0.87%)~5.08s5.19sp=0.462 n=6
Bind Time2.25s (± 1.39%)2.27s (± 1.77%)~2.21s2.31sp=0.373 n=6
Check Time25.96s (± 0.43%)25.91s (± 0.34%)~25.78s26.01sp=0.422 n=6
Emit Time0.00s (±244.70%)0.00s (±154.76%)~0.00s0.01sp=0.595 n=6
Total Time33.38s (± 0.34%)33.34s (± 0.27%)~33.25s33.48sp=0.575 n=6
xstate-main - node (v18.15.0, x64)
Errors55~~~p=1.000 n=6
Symbols570,733573,794+3,061 (+ 0.54%)~~p=0.001 n=6
Types191,446191,468+22 (+ 0.01%)~~p=0.001 n=6
Memory used501,309k (± 0.01%)502,066k (± 0.02%)+757k (+ 0.15%)501,986k502,217kp=0.005 n=6
Parse Time4.29s (± 0.32%)4.32s (± 0.31%)+0.03s (+ 0.62%)4.30s4.33sp=0.016 n=6
Bind Time1.54s (± 1.58%)1.54s (± 0.58%)~1.53s1.55sp=1.000 n=6
Check Time24.92s (± 0.30%)24.84s (± 0.24%)~24.77s24.93sp=0.226 n=6
Emit Time0.00s (±244.70%)0.00s~~~p=0.405 n=6
Total Time30.75s (± 0.33%)30.70s (± 0.15%)~30.65s30.77sp=0.470 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
Collaborator

@ahejlsberg Here are the results of running the top 400 repos with tsc comparing main and refs/pull/61668/merge:

Everything looks good!

Copy link
Member

@weswighamweswigham left a comment

Choose a reason for hiding this comment

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

Q: If the issue seems to be that we shouldn't ever get the input type parameter as an inference result, doesn't that imply we should never make it available in inference as an option to match in the first place? Eg, we should always be matching against a clone that we later instantiate to inference results/constraints, as was already done within an implementation signature?

@weswigham
Copy link
Member

We then subsequently make a better inference of 1 for A.

That implies 1 is contextually typing itself, for it to acquire a literal type like that, which seems wrong, given the tautological nature - it should really be number.

@ahejlsberg
Copy link
MemberAuthor

Q: If the issue seems to be that we shouldn't ever get the input type parameter as an inference result, doesn't that imply we should never make it available in inference as an option to match in the first place?

Not quite sure I understand your question. When inferring for a generic function call, we do want the type parameters of that call to appear in contextual types for arguments (and we have logic to ensure they're instantiated with fixing or non-fixing mappers as appropriate), but we do not want type parameters of any containing function calls to appear. Hence the createOuterReturnMapper function that ensures any such type parameters are instantiated.

@ahejlsberg
Copy link
MemberAuthor

That implies 1 is contextually typing itself, for it to acquire a literal type like that, which seems wrong, given the tautological nature - it should really be number.

The fact that we infer type 1 is just a reflection of the rules we have for widening in type inference. The situation corresponds to:

declarefunctioncall<A,R>(f: (x: A)=>R,arg: A): Rdeclarefunctionid(x: unknown): unknown;call(id,1)// Infers type `1` for `A`

Above, we have two inferences for A, unknown and 1. Since one of the inferences is not to a top-level occurrence of the type parameter, we perform no widening. The rules are a bit obtuse, but they are what they are. The 1 is definitely not contextually typing itself.

jakebailey
jakebailey previously approved these changes Jun 5, 2025
Copy link
Member

@jakebaileyjakebailey left a comment

Choose a reason for hiding this comment

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

Is there anything else left to do here?

@github-project-automationgithub-project-automationbot moved this from Not started to Needs merge in PR BacklogJun 5, 2025
@jakebailey
Copy link
Member

Hm, are we worried about those fp-ts breaks?

@jakebaileyjakebailey dismissed their stale reviewJune 6, 2025 19:32

rechecking

@ahejlsberg
Copy link
MemberAuthor

Hm, are we worried about those fp-ts breaks?

I'm not concerned with those. They're tests that check for exact types and, as expected, the types have changed. The new inferred types aren't per se worse, they're just different

@jakebailey
Copy link
Member

jakebailey commented Jun 7, 2025

I guess, but it's seemingly pretty simple, "does our isSome call filtered preserve the tupleness of this other thing", and now it doesn't.

constactual1=_.filter(O.isSome)([O.some(3),O.some(2),O.some(1)])U.deepStrictEqual(actual1,O.some([O.some(3),O.some(2),O.some(1)]))

(#61668 (review) felt pretty correct to me)

@mbest
Copy link
Member

I have code using MobX's observable.map that errors in 5.9 possibly because of this change (I couldn't find anything else in the docs)

Here is the code working in TypeScript 5.8

Here is the same code in TypeScript 5.9

The error is:

Argument of type '(string | Application)[][]' is not assignable to parameter of type 'IObservableMapInitialValues<string | Application, string | Application> | undefined'. Type '(string | Application)[][]' is not assignable to type 'IMapEntries<string | Application, string | Application>'. Type '(string | Application)[]' is not assignable to type 'IMapEntry<string | Application, string | Application>'. Target requires 2 element(s) but source may have fewer.(2345) 

I've also included in the example using new Map to show that pattern is still supported in 5.9.

const createAppReportMapMobX = (data: readonly ApplicationUsageData[]) =>{// Errors return observable.map( data.map(app => [ app.preferredAppId, createAppReport(app.preferredAppId, app.dailyAverageUsage, app.dailyApplicationUsages) ]))}; const createAppReportMapPlain = (data: readonly ApplicationUsageData[]) =>{// OK return new Map( data.map(app => [ app.preferredAppId, createAppReport(app.preferredAppId, app.dailyAverageUsage, app.dailyApplicationUsages) ]))}; 

@jakebailey
Copy link
Member

Please file an issue if you're having trouble, we cant track comments in old PRs

@mbest
Copy link
Member

mbest commented Sep 3, 2025

I opened a PR on MobX to fix the issue. It's not clear why this change in TS caused the problem, but my "fix" is there: mobxjs/mobx#4578

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

Labels

Author: TeamFor Backlog BugPRs that fix a backlog bug

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Type variable leak and odd error React's ComponentProps type issues in TypeScript 5.6.2

7 participants

@ahejlsberg@typescript-bot@weswigham@jakebailey@mbest@RyanCavanaugh