microsoft / microsoft/TypeScript

Regression: recursive conditional+mapped "serialize" type no longer proves `Transform<X>` assignable to `X` on deeply-nested compound types (native-preview; works in tsc)

Offen
#63,845 9 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

Needs More Info
Vorherrschende Sprache
Go
Sterne
111k
Forks
14.3k
Ø Merge
2 T. 4 Std.
Gemergte PRs (30 T.)
132

Beschreibung

## Environment
- `@typescript/native-preview` (tsgo)
- **Last good:** `7.0.0-dev.20260421.2`
- **Broken:** `7.0.0-dev.20260618.1` … `7.0.0-dev.20260622.1` (latest) — all fail
- Stable `typescript@5.9.3`: **OK** (accepts the code)

So: same source, only the native-preview version changed → a tsgo regression somewhere between `20260421.2` and `20260618.1`.

## What breaks
A common recursive "serialize" utility type — maps `Date | bigint` → `string` recursively through objects and arrays, leaving everything else unchanged (so for a type `X` containing **no** `Date`/`bigint`, `Transform` is structurally identical to `X`):

```ts
type Transform = {
[K in keyof Base]: Exclude extends never ? Base[K]
: Exclude extends object ? (Exclude extends From ? To | Extract : Transform)
: Base[K];
};
type TransformJson = Transform;
```

For a **deeply-nested compound** type — recursion + arrays + an 8-member **discriminated union with a shared base** (`{base} & ({type:1;…} | {type:2;…} | …)`) nested several levels behind arrays — `tsgo` fails to prove `TransformJson` assignable to `X` even when `X` has no `Date`/`bigint` (i.e. when the transform is provably the identity):

```
error TS2322: Type 'Transform<…, bigint | Date, string>' is not assignable to type '…'.
Type 'Transform<{base} & (…union…), bigint | Date, string>' is not assignable to '{base} & (…union…)'.
```

`tsc` proves this assignable; `tsgo` (new builds) does not.

## Diagnosis / things tried (in case it helps narrow the regressed area)
- Adding an up-front "does this subtree contain `From`?" guard so the transform returns `Base` verbatim for no-`From` subtrees → flips the failure into **`TS2589` "Type instantiation is excessively deep and possibly infinite"** across the project, i.e. the extra recursive pass exhausts a depth/instantiation budget.
- Bounding the transform's recursion depth (no extra pass) → tsgo then *fully expands* the type (no TS2589) but **still** rejects the expanded `{base} & union` intersection-with-union assignment.
- So it looks like two compounding limits: (a) a recursion/instantiation budget that's tighter or counted differently than in tsc, and (b) assignability of a mapped-type result back to an intersection-with-union, at depth.

## Reproduction note (the awkward part)
I could **not** reduce this to a small standalone repro: the minimal/standalone versions of the exact pattern (even with the same 8-member intersection-with-union behind arrays) compile **clean** under both tsgo and tsc. It only reproduces inside a large real project (many hundreds of interacting `Transform<…>` instantiations across the program), which points at a **scale-dependent / cumulative** instantiation budget rather than a single-type defect.

Happy to help bisect against the dev-build range, or to share a private reproduction with the team if that's an option.

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
  3. Forke das Repository und arbeite in einem Branch.
  4. Öffne einen Pull Request, der die Issue-Nummer nennt.

Rechercherichtung

Beginne damit, die native-preview-Builds zwischen 7.0.0-dev.20260421.2 und 7.0.0-dev.20260618.1 per Bisect zu untersuchen, und vergleiche tsgo mit tsc anhand des gemeldeten Projektmusters. Untersuche das Rekursions- oder Instanziierungsbudget sowie die Zuweisbarkeit tief verschachtelter mapped types; als abgeschlossen gilt die Aufgabe, wenn sich die Regression reproduzieren lässt, TS2589 vermieden wird und die Zuweisung wieder funktioniert, ohne bestehendes Verhalten zu beeinträchtigen.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
go, typescript
Bereich
compilers
Issue-Typ
Bug
Schwierigkeit
5/5
Geschätzter Aufwand
Über eine Woche
Aktivitätsstatus
Ruhig
Klarheit
Muss geklärt werden
Anfängerfreundlichkeit
28/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.