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)
还没有人认领这个 Issue。
- 主要语言
- Go
- 星标
- 111k
- 派生
- 14.3k
- 平均合并
- 2 天 4 小时
- 30 天内合并 PR
- 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` 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.
贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
调研方向
首先对 7.0.0-dev.20260421.2 和 7.0.0-dev.20260618.1 之间的 native-preview 构建进行二分查找,在报告的项目模式上比较 tsgo 与 tsc。调查递归或实例化预算以及深层 mapped-type 的可赋值性;完成的标准是能够复现回归、避免 TS2589,并在不破坏现有行为的情况下恢复赋值。
由索引模型根据 Issue 内容生成。
评估
- 技术栈
- go, typescript
- 领域
- compilers
- Issue 类型
- 缺陷
- 难度
- 5/5
- 预计耗时
- 一周以上
- 活跃度
- 冷清
- 描述清晰度
- 需要澄清
- 新手友好度
- 28/100