Typescript: Variadic element of tuple-like intersection types are spreading incorrectly

Created on 5 Oct 2020  ·  4Comments  ·  Source: microsoft/TypeScript


TypeScript Version: 4.0.3


Search Terms: variadic tuple, variadic element, intersection type, tuple-like type

Code

type T1 = [...unknown[] & []]; // never[]
type T2 = [...number[] & [1, 2, 3]]; // (3 | 1 | 2)[]

Expected behavior: for T1, I expected it to be [](empty tuple type) and for T2, I expected it to be [1, 2, 3].

Actual behavior: Both T1 and T2 became Array rather than tuple somehow. (T1 is deduced to never[], T2 is deduced to (3 | 1 | 2)[])

detailed explanation

In some perspective, unknown could be recognized as type of all types. Therefore, [unknown] is type of all type-level 1-tuples and intuitively, unknown[] is type of all type-level n-tuples.

So [] <: unknown[] is true (i.e. all empty type-level tuple is subtype of all type-level n-tuples) and you can check it simply with this code:

type M = [] & unknown[] extends [] ? [] extends [] & unknown[] ? true : false : false; // true

However, in spite of the fact that [] is subtype of unknown[] therefore [] & unknown[] is actually [], variadic element of [] & unknown[] somehow spreads as never[], which is incorrect and unintuitive.

Playground Link: Playground

Bug

Most helpful comment

I was building type-level programming library since TS 4.1 finally added recursive conditional type alias. But after few hours, I encountered this issue and talked with others in twitter for a few days. That 👍seems to be added by people I know or discussed with me about this.

All 4 comments

incorrect and unintuitive

Unintuitive, yes; not as good as we could do, yes; but “incorrect” is somewhat debatable. (As an aside, this issue led to a great conversation about whether never[] is conceptually the same as [], despite specific differences in their assignability.) At any rate, since never[] is not assignable to [], that’s a good argument for T1 being “incorrect,” but (3 | 1 | 2)[] is clearly a valid representation of [1, 2, 3]; it’s just not a very good one 😄

Out of curiosity, since there are 4 👍 on an issue that seems somewhat arcane, is this coming up in practice somewhere?

I was building type-level programming library since TS 4.1 finally added recursive conditional type alias. But after few hours, I encountered this issue and talked with others in twitter for a few days. That 👍seems to be added by people I know or discussed with me about this.

I agree on that T1 is not being incorrect, sorry for misusing word. However, I think we all agree on that ( 3 | 2 | 1 )[] is not a proper or useful typing at all at this point since some important informations are discarded and it might cause some unexpected problems. 🙂

(Sorry for loose formatting, I wrote this comment with my mobile phone...)

I was building type-level programming library since TS 4.1 finally added recursive conditional type alias. But after few hours, I encountered this issue and talked with others in twitter for a few days. That 👍seems to be added by people I know or discussed with me about this.

Similar scenario for me. I was trying to map nested tuple types.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Roam-Cooper picture Roam-Cooper  ·  3Comments

zhuravlikjb picture zhuravlikjb  ·  3Comments

dlaberge picture dlaberge  ·  3Comments

kyasbal-1994 picture kyasbal-1994  ·  3Comments

DanielRosenwasser picture DanielRosenwasser  ·  3Comments