microsoft / microsoft/TypeScript
Spread operator fails to distribute over union when recursive type call is inlined instead of aliased
Chưa có ai nhận issue này.
- Ngôn ngữ chính
- Go
- Star
- 111k
- Fork
- 14.3k
- Merge trung bình
- 2 ngày 4 giờ
- Pull request đã merge (30 ngày)
- 132
Mô tả
🔎 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
💻 Code
type CrossProduct<Union, Counter extends unknown[]> =
Counter extends [infer Zero, ...infer Rest]
? (Union extends infer Member
? [Member, ...CrossProduct<Union, Rest>]
: never)
: [];
let test1: CrossProduct<number | string, [undefined]>; // [string] | [number]
type Depth1 = CrossProduct<number | string, [undefined]> // [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<number | string, [undefined]>]: 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.
Hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Hướng nghiên cứu
Bắt đầu với bản tái hiện TypeScript Playground được liên kết và so sánh các kiểu đã được đánh giá của test2, test3 và test4. Truy dấu lời gọi CrossProduct đệ quy và cách xử lý spread trong type checker; hoàn tất khi test3 được đánh giá thành cùng một union được phân phối đầy đủ như test2 và test4.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- typescript
- Lĩnh vực
- compilers
- Loại issue
- Lỗi
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức độ hoạt động
- Đình trệ
- Độ rõ ràng
- Khá rõ ràng
- Mức phù hợp với người mới
- 38/100