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)

未关闭
#63,845 9 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

Needs More Info
主要语言
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.

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 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

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。