question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Variadic element of tuple-like intersection types are spreading incorrectly

See original GitHub issue

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

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:7
  • Comments:6 (2 by maintainers)

github_iconTop GitHub Comments

2reactions
ENvironmentSetcommented, Oct 7, 2020

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.

1reaction
andrewbranchcommented, Oct 7, 2020

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?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Documentation - TypeScript 4.0
Variadic Tuple Types ... Consider a function in JavaScript called concat that takes two array or tuple types and concatenates them together to...
Read more >
How to map & index into tuple types that is generically spread ...
Where TC is a special type constructor that maps Resources to the 2nd element of each return type and still preserves the tuple...
Read more >
TypeScript: Variadic Tuple Types Preview - fettblog.eu
A variadic tuple type is a tuple type that has the same properties — defined length and the type of each element is...
Read more >
The Ceylon Language
The type of a function is expressed within the type system as an instantiation of the interface Callable. The parameter types are expressed...
Read more >
4. Functions - Programming TypeScript [Book] - O'Reilly
Like in object and tuple types, you can use ? to mark parameters as optional. ... and spreads its second argument over your...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found