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)
まだ誰も着手していません。
- 主要言語
- Go
- スター
- 111k
- フォーク
- 14.3k
- 平均マージ
- 2日 4時間
- マージ済み PR(30日)
- 132
説明
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<X> is structurally identical to X):
type Transform<Base, From, To> = {
[K in keyof Base]: Exclude<Base[K], undefined | null> extends never ? Base[K]
: Exclude<Base[K], undefined | null> extends object ? (Exclude<Base[K], undefined|null> extends From ? To | Extract<Base[K], null|undefined> : Transform<Base[K], From, To>)
: Base[K];
};
type TransformJson<T> = Transform<T, Date | bigint, string>;
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<X> 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 returnsBaseverbatim for no-Fromsubtrees → flips the failure intoTS2589"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} & unionintersection-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.
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
調査の方向性
まず、7.0.0-dev.20260421.2 と 7.0.0-dev.20260618.1 の間で native-preview ビルドを bisect し、報告されたプロジェクトパターンで tsgo と tsc を比較します。再帰またはインスタンス化の予算と、深い mapped-type の代入可能性を調査します。完了の条件は、リグレッションを再現でき、TS2589 を回避し、既存の動作を壊さずに代入を復元できることです。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- go, typescript
- 領域
- compilers
- issue の種類
- バグ
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 活発さ
- 静か
- 明瞭さ
- 説明が足りない
- 初心者へのやさしさ
- 28/100