7.1 regression: comparing a recursive `-?` mapped type is quadratic in the number of properties and hits TS2589 (since typescript-go#4820)
Les mainteneurs répondent en général sous 1 jour
Personne n'a encore pris cette issue.
Évaluation
- Difficulté
- 4/5
- Temps estimé
- 3-5 jours
- Accessibilité débutants
- 48/100
- Type d'issue
- Bug
- Clarté
- Clairement spécifiée
- Activité
- Active
- Stack technique
- go, typescript
- Domaine
- compilers, performance
Piste de recherche
Start by reading the variance computation change in microsoft/typescript-go#4820, then reproduce the issue with the supplied one-file repro and tsc -p . --singleThreaded --extendedDiagnostics. Compare instantiation counts for the last good and first bad builds, focusing on the recursive Builder interface, its -? mapped type, and changing S | K argument. Done means the comparison stays near linear in property count and the 500-property repro succeeds without TS2589.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Description
🔎 Search Terms
variance, TS2589, excessively deep, instantiation count, mapped type, -?, quadratic, 7.1 regression
🕗 Version & Regression Information
- Last good:
7.1.0-dev.20260805.1(gitHead 12318e599d) - First bad:
7.1.0-dev.20260806.1(gitHead 86cc4767d4) - That range is one commit: microsoft/typescript-go#4820, "Order variance computation by associated type symbol".
- Still failing on
7.1.0-betaand7.1.0-dev.20261024.1. - 7.0.2 accepts the code.
Same commit as #64891 and #64930, but this one is about performance: the comparison finishes with a correct result
for small types, it just costs quadratically more instantiations, and on real types it hits the 5M cap.
⏯ Playground Link
The 7.1 builds aren't available in the Playground. CLI repro: one file in an empty directory, tsc -p . --singleThreaded --extendedDiagnostics.
tsconfig.json
{ "compilerOptions": { "strict": true, "noEmit": true, "types": [] }, "files": ["repro.ts"] }
💻 Code
type D = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
type Entity = Record<`f${'0' | '1' | '2' | '3' | '4'}${D}${D}`, string> // 500 properties
interface Method<T, K extends keyof T, S> {
(): Builder<T, S | K>
}
type Builder<T, S = never> = { [K in keyof T]-?: Method<T, K, S> }
declare const builder: Builder<Entity>
export const widened: Builder<Entity & object> = builder
🙁 Actual behavior
repro.ts(10,14): error TS2589: Type instantiation is excessively deep and possibly infinite.
Instantiations: 5003892 Check time: 79 s
🙂 Expected behavior
No error, as in 7.0.2 and 7.1.0-dev.20260805.1: about 9k instantiations, 0.04 s check time.
Additional information about the issue
With 100 properties (Record<`f${D}${D}`, string>) there is no error, but the count goes from 5,105 to 256,939
instantiations. It grows with the square of the property count: about 66k at 50 properties, 1M at 200 and the 5M cap
near 460.
| build | 100 props: instantiations | 500 props |
|---|---|---|
| 7.0.2 | 5,105 | 9,105, ok |
7.1.0-dev.20260805.1 (12318e599d) |
5,105 | 9,105, ok |
7.1.0-dev.20260806.1 (86cc4767d4) |
256,939 | TS2589 |
| 7.1.0-dev.20261024.1 | 258,143 | TS2589 |
All three of these are needed for the quadratic count; removing any one brings it back to linear:
- the
-?modifier on the homomorphic mapped type; Methodas a generic interface that referencesBuilderagain (with an inline() => Builder<T, S | K>both
7.0.2 and 7.1 are quadratic, so the regression is in how the interface's variance gets computed);- a type argument that actually changes, here
S | K(withBuilder<T, S>it stays linear).
The target also has to be a different but equivalent instantiation (Entity & object); a structurally identical
mapped copy of Entity does not trigger it.
Real-world impact: this is a reduced form of a fluent "selection builder" type from our library, whose
entity types resolve through UnionToIntersection<E> & object, so every selector is compared against
Builder<E & object>. On a ~2,100-file app under 7.1:
- TS2589 appears on ordinary selector call sites, and the callbacks' destructured parameters cascade into TS7031/TS7006.
- The depth error leaves the checker's caches in a bad state, so a later file that checks cleanly on its own reports
TS2339 (members missing on the builder's result type). The error count depends on--checkersand on which files
share a checker (0 to 77). - The project checks
--singleThreadedin 25 s / 2.6 GB on7.1.0-dev.20260805.1; on7.1.0-dev.20260930.4the
same run was OOM-killed at an 18 GB cap, and with default checkers it reached 24 GB before being killed.
- Langage dominant
- Go
- Étoiles
- 112k
- Forks
- 15.4k
- Merge moyen
- 2 j 21 h
- PR mergées (30 j)
- 126
Préparer son environnement
Lance le conteneur de développement du projet dans votre navigateur, avec votre propre compte GitHub.
- Aucun Dockerfile ni fichier Docker Compose
- Propose un modèle de pull request
- Lire le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Autres issues de microsoft/TypeScript
-
Won't Fix
Difficulté 2/5 1-3 heures Accessibilité débutants 62/100
microsoft/TypeScript#65107 · 1 commentaire ·
Les mainteneurs répondent en général sous 1 jour
-
Native API: formatDiagnosticsWithColorAndContext drops related information without a file locationPeut-être pris @timurzvural l’a pris aujourd’hui. Ouverte
Difficulté 2/5 1-3 heures Accessibilité débutants 75/100
microsoft/TypeScript#65087 ·
Les mainteneurs répondent en général sous 1 jour
-
TS7 LSP: documentHighlight returns nothing when the file path contains '@'Peut-être à nouveau libre Une pull request pour cette issue a été fermée sans être fusionnée. OuverteBug
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
microsoft/TypeScript#64758 ·
Les mainteneurs répondent en général sous 1 jour
-
Language server (tsc --lsp) exits with code 1 after `shutdown` and `exit`Peut-être pris @rajnish-verma-22172 l’a pris il y a 13 jours. OuverteBug
Difficulté 2/5 1-3 heures Accessibilité débutants 76/100
microsoft/TypeScript#64742 · 1 commentaire ·
Les mainteneurs répondent en général sous 1 jour
-
Class names `eval` and `arguments` are not reported as invalid strict mode bindingsPeut-être pris @dmety l’a pris il y a 26 jours. OuverteBug
Difficulté 2/5 1-3 heures Accessibilité débutants 68/100
microsoft/TypeScript#64661 ·
Les mainteneurs répondent en général sous 1 jour
Toutes les issues de microsoft/TypeScript
Issues similaires
-
Difficulté 2/5 1-3 heures Accessibilité débutants 84/100
hyperledger/fabric-x-orderer#1409 ·
Les mainteneurs répondent en général sous 3 jours
-
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
Les mainteneurs répondent en général sous 1 jour
-
needs-area
Difficulté 2/5 1-3 heures Accessibilité débutants 68/100
Azure/typespec-azure#5936 ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 1/5 Moins d'une heure Accessibilité débutants 70/100
-
Fix mode unpins a reusable workflow call when the same repository is also used as a step actionOuverte
Difficulté 2/5 1-3 heures Accessibilité débutants 72/100
github/gh-actions-lock#261 ·
Les mainteneurs répondent en général sous 1 jour