microsoft / microsoft/TypeScript
tsserver hangs indefinitely when inferring return type of class method that passes this to a function with deeply nested conditional return type
- 主要语言
- Go
- 星标
- 111k
- 派生
- 14.3k
- 平均合并
- 2 天 4 小时
- 30 天内合并 PR
- 132
描述
### 🔎 Search Terms
hang circular
### 🕗 Version & Regression Information
This behavior is present in TypeScript 5 and TypeScript 6 beta.
### ⏯ Playground Link
N/A — requires the remeda package (npm i remeda). Reproduction is a self-contained file below.
### 💻 Code
```ts
import { pick } from "remeda";
export class MyClass {
constructor(public readonly field: number) {}
// [bad] tsserver hangs indefinitely: no explicit return type
getIdentity() {
return pick(this, ["field"]);
}
// [good] works fine: explicit return type breaks the cycle
getIdentityFixed(): Pick {
return pick(this, ["field"]);
}
}
```
### 🙁 Actual behavior
`tsserver` becomes completely unresponsive. The editor (VS Code) loses all language service features (hover types, completions, diagnostics) until tsserver is manually restarted. No error is emitted; tsserver simply loops forever.
The cause is an undetected circular type inference chain. To infer the return type of `getIdentity()`, TypeScript must evaluate `PickFromArray` (remeda's `pick` return type). That involves `IsBoundedRecord` → `IsBounded>`. `KeysOfUnion` uses `UnionToIntersection`, which places `MyClass` in a contravariant function parameter position — forcing eager, non-deferred evaluation of the full structural type of `MyClass`. The full type of `MyClass` includes `getIdentity: () => `, whose inferred return type is what we started trying to compute. Because the cycle passes through ~5 distinct type alias instantiations, TypeScript's cycle-detection heuristics never fire, and the checker loops indefinitely instead of emitting a "circularly references itself" error.
### 🙂 Expected behavior
TypeScript should detect the circular inference and either:
- Emit a "Return type annotation circularly references itself" error (as it does for simpler cycles), or
- Fall back to any with a warning.
Either outcome is acceptable. The checker should never hang.
### Additional information about the issue
Workaround: add an explicit return type annotation to the method. This gives TypeScript the type of `MyClass.getIdentity()` upfront, preventing the cycle from forming.
贡献指南
调研方向
首先安装 remeda,并使用 tsserver 运行自包含的 TypeScript 重现代码。将卡住的推断返回类型案例与显式的 Pick 注解进行比较,然后跟踪报告中的 PickFromArray、IsBoundedRecord、IsBounded、KeysOfUnion 和 UnionToIntersection 链周围的循环处理逻辑。完成标准是 tsserver 不再卡住,并且要么报告循环返回类型错误,要么在发出警告的情况下回退到 any。
由索引模型根据 Issue 内容生成。
评估
- 技术栈
- typescript
- 领域
- compilers
- Issue 类型
- 缺陷
- 难度
- 5/5
- 预计耗时
- 一周以上
- 活跃度
- 停滞
- 描述清晰度
- 基本清楚
- 新手友好度
- 35/100