Fixed mapped types not being considered as homomorphic with substitution constraints - #4596
Conversation
There was a problem hiding this comment.
Pull request overview
This PR fixes a TypeScript checker behavior in the Go port so that mapped types remain homomorphic even when their keyof T constraint flows through a substitution type (matching the regression described in microsoft/TypeScript#63132). It also adds a targeted compiler regression test and commits the corresponding reference baselines.
Changes:
- Unwrap substitution types when detecting a homomorphic mapped type variable, so
keyof T extends ... ? { [K in keyof T]: ... } : ...continues to be recognized as homomorphic. - Add a new compiler test case reproducing the scenario from the linked upstream issue.
- Add committed
.typesand.symbolsreference baselines for the new test.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
internal/checker/checker.go |
Adjusts homomorphic mapped type detection to use the “actual” (unsubstituted) type variable. |
testdata/tests/cases/compiler/mappedTypeNotMistakenlyHomomorphic2.ts |
New regression test covering homomorphic behavior through conditional wrapping. |
testdata/baselines/reference/compiler/mappedTypeNotMistakenlyHomomorphic2.types |
Reference type baseline for the new test. |
testdata/baselines/reference/compiler/mappedTypeNotMistakenlyHomomorphic2.symbols |
Reference symbol baseline for the new test. |
|
TypeScript Bot (@typescript-bot) test it |
|
Jake Bailey (@jakebailey) Here they are:
tscComparison Report - baseline..pr
System info unknown
Hosts
Scenarios
Developer Information: |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Jake Bailey (@jakebailey) Here are the results of running the top 400 repos with tsc comparing Something interesting changed - please have a look. Details
|
|
Hmmmm, this is a break? |
|
Jake Bailey (@jakebailey) this is kinda expected. A distributive homomorphic type requires to be written in this form (roughly): type M<T> = {
[K in keyof T]: T[K]
}A type-fest-based repro case can be seen here. As we can see, that exact form ( But because of the issue fixed by this PR, that mapped type was not recognized as homomorphic and distributive. That happened because It's common to change the code a little bit to enable/disable distributivity of conditional types and I think the same principle kinda applied to mapped types, given the distributivity (or the lack of it) is also an implied trait of any mapped type. I just pushed out a test documenting this and showcasing 2 possible workarounds for the |
fixes microsoft/TypeScript#63132