Don't reduce intersections of mappings of the same object type - #64481
Anders Hejlsberg (ahejlsberg) wants to merge 3 commits into
Conversation
|
TypeScript Bot (@typescript-bot) test it |
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
The broad exemption prevents valid conflicting mapped intersections from reducing to never.
Review effort: Balanced
Findings: 1
What changed in this PR
Prevents eager intersection reduction during recursive Zod-style schema inference.
Changes:
- Detects mapped intersections sharing an object source.
- Adds regression coverage and updates inferred-type baselines.
| File | Description |
|---|---|
tsc/internal/checker/checker.go |
Skips reduction for same-source mapped intersections. |
tsc/testdata/tests/cases/compiler/recursiveTypeInference2.ts |
Adds the Zod regression case. |
tsc/testdata/baselines/reference/compiler/recursiveTypeInference2.types |
Records inferred types. |
tsc/testdata/baselines/reference/compiler/recursiveTypeInference2.symbols |
Records resolved symbols. |
tsc/testdata/baselines/reference/compiler/recursiveTypeInference.types |
Updates existing recursive inference results. |
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
| if t.objectFlags&ObjectFlagsIsNeverIntersectionComputed == 0 { | ||
| t.objectFlags |= ObjectFlagsIsNeverIntersectionComputed | ||
| if core.Some(c.getPropertiesOfUnionOrIntersectionType(t), c.isNeverReducedProperty) { | ||
| if !c.isMappingOfSameObjectType(t.Types()) && core.Some(c.getPropertiesOfUnionOrIntersectionType(t), c.isNeverReducedProperty) { |
There was a problem hiding this comment.
True, but the goal here is to implement a heuristic that defers intersection reduction in cases where it is highly unlikely that impossible intersections will occur. An intersection consisting solely of homomorphic mapped types applied to the same object type is typically a conditional mapping that applies different templates to non-overlapping subsets of properties, and intersection reduction doesn't affect such types--except it forces eager member resolution for the constituent object type. Which is what we want to avoid.
|
Anders Hejlsberg (@ahejlsberg) Here they are:
tscComparison Report - baseline..pr
System info unknown
Hosts
Scenarios
Developer Information: |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Anders Hejlsberg (@ahejlsberg) Here are the results of running the user tests with tsc comparing There were infrastructure failures potentially unrelated to your change:
Otherwise... Everything looks good! |
|
Hey Anders Hejlsberg (@ahejlsberg), the results of running the DT tests are ready. Everything looks the same! |
|
Apparently this pattern accounts for a substantial number of types in mui-docs, so nice savings there. |
|
Anders Hejlsberg (@ahejlsberg) Here are the results of running the top 400 repos with tsc comparing Everything looks good! |

With this PR, when a mapped type is applied to an intersection of homomorphic mappings of the same object type, we longer attempt to reduce the intersection. This in turn means that we don't eagerly resolve the members of the target object type, which helps enable creation of recursive schemas in Zod and similar libraries.
Fixes #64415.