microsoft / microsoft/TypeScript

Spread operator fails to distribute over union when recursive type call is inlined instead of aliased

オープン
#62,812 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る
Bug Domain: Conditional Types Help Wanted
主要言語
Go
スター
111k
フォーク
14.3k
平均マージ
2日 4時間
マージ済み PR(30日)
132

説明

### 🔎 Search Terms

distribution, spread

### 🕗 Version & Regression Information

This is the behavior in every version I tried from version 4.1.5 upwards to 5.9.3 and in nightly v6.0.0-dev.20251127

### ⏯ Playground Link

https://www.typescriptlang.org/play/?ts=5.9.3#code/C4TwDgpgBAwgTgewM5IAqICYFcDGwA8AqgHYCWCxANLAlscBHFBAB4PEZJR0DWxCAd2IBtALoA+KAF4AUFHk06DJq3acow0sQBmjKAC1GCagDozW3UwBKEJMFFyFAfigAKEuWLM2EDlwt6ALIQALYARoyOCs4aweGMpmbwyGiYuAQeFNQ2duIO0dEAXFDEEABujACUUVDFYgDcMgA2EMBQDHYAjMXJKOgI2Hj4xFjxTAA+UHZwWgDm1MJ0GBDaWhAYEvXyAPTbGtNzolCTwiNjDqCQUAAiEGDAABad0rCIfWlDZxETU8AzxPMNEsVmsNpJdvs-odjhovowHC02h1gAAmYquOE-A4A7xqfw6PSZLwudxkCi43zqXj8IRQFzCImJEy3e5PUTFUoVOCVWolcpVLYQ4TYwEio4nTHUTHiyH-QHSmGnUbfahi5qtdq2YAAZnRmJhIopfigASYRLpbnNqkpXGpgmJGkZUDMJl6qQG6WGyr0kxFC2Bq1KYPZfK5PI5-O5Wx2e2FUIBqvjsxlSrGUu9cARGuRABY9RmDUmjepTVBzSSrT5jXbafSnS7XHG5SnpZUQ5yqryO1GoEK-b9m4rJSUMyn+wqJRnE82ZEA

### 💻 Code

```ts
type CrossProduct =
Counter extends [infer Zero, ...infer Rest]
? (Union extends infer Member
? [Member, ...CrossProduct]
: never)
: [];
let test1: CrossProduct; // [string] | [number]
type Depth1 = CrossProduct // [string] | [number]
let test2: (number | string extends infer Union ? (Union extends unknown ? [Union, ...Depth1]: never) : never); // [string, string] | [number, number] | [string, number] | [number, string]
let test3: (number | string extends infer Union ? (Union extends unknown ? [Union, ...CrossProduct]: never) : never); // [string, string] | [number, number]
let test4: (number | string extends infer Union ? (Union extends unknown ? [Union, ...([string] | [number])]: never) : never); // [string, string] | [number, number] | [string, number] | [number, string]
```

### 🙁 Actual behavior

The types of test2 and test4 evaluate to the correct, expected, fully distributed type, while the type of test3 is incompletely distributed (as displayed by IntelliSense in the Playground).

The only difference between test2 and test3 is that in test3 the type that is aliased as Depth1 in test2 is inlined in test3. Thus, both should evaluate to the same type. The type of test2 is correct.

test4 also evaluates correctly. Here the alias is replaced by the literal evaluation result.

### 🙂 Expected behavior

The type of variable test3 should evaluate to

[string, string] | [number, number] | [string, number] | [number, string]

But it evaluates to

[string, string] | [number, number]

### Additional information about the issue

This problem matters since the recursive call in test3 is what I actually need for the construction of a respective recursive type.

コントリビューションガイド

コントリビューションガイドを開く

調査の方向性

リンクされている TypeScript Playground の再現コードから始め、test2、test3、test4 の評価結果の型を比較します。type checker 内の再帰的な CrossProduct 呼び出しと spread の処理を追跡します。test3 が test2 および test4 と同じ完全に分配された union として評価されれば完了です。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
typescript
領域
compilers
issue の種類
バグ
難易度
4/5
見積もり時間
3〜5日
活発さ
停滞
明瞭さ
おおむね明確
初心者へのやさしさ
38/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。