As per @KyleMit's request, this answer combines my comments into one formal block
If you must work with a "dynamic tuple", I highly suggest looking at the original answer on the linked question. It approaches the problem the other way around. Which, all things considered, is the only way to do what OP strictly asks for. You don't create the type of alternating pairs, you validate whether something falls under the type of alternating pairs.
I am, instead, going to talk about why creation of such a type is problematic, and offer an alternative representation of said "alternating pairs" type.
Why not?
The fundamental issue in making an "alternating pairs" type (or any dynamic "pair" type) is that a pair is strictly a tuple. In type theory, a tuple is a product type and thus memorizes each of its (possibly-)distinct resident types alongside their positional information.
The type [T, U]
reads "A pair where T
is the type of the first value, and U
is the type of the second value". The type [T, U, T]
is completely distinct from [T, U]
. Even though typescript tuples are just javascript arrays, the difference is substantial in the type system. There simply is no way to have a dynamic tuple type, as a product type is exact and static.
What is an array, then?
An array is a homogenous collection. In type theory, an "array" (eh, it's more of a cons list but whatever) merely needs to hold the type of its residents overall, it doesn't care about their positions, and it doesn't care about its length (well, unless we're talking about dependent types - but that's a rabbit hole for another day). Notice how [1, "foo", True]
, when used as an array, has the type Array<number | string | boolean>
. Its overall resident type is indeed number | string | boolean
and it doesn't remember where exactly they are placed. You may add any type that is assignable to number | string | boolean
to this array.
Another perspective
I want to take a moment to roll everything back. Going full abstract, OP's goal is a "dynamic, sequential collection of pairs". A dynamic, sequential collection is an array (not a static tuple). And a pair is.... a tuple. What if, instead of this-
[T, U]
or [T, U, T, U]
or [T, U, T, U, T, U]
ad infinitum
We paired up the pairs to get-
[(T, U)]
or [(T, U), (T, U)]
or [(T, U), (T, U), (T, U)]
ad infinitum
NOTE: That's not JS/TS syntax, I used parentheses there for clarity, tuples are, of course, represented with angle brackets instead ([[T, U], [T, U]...]
).
Homogeneity - the one characteristic needed to have a dynamic sequential collection. That last type is just Array<[T, U]>
or [T, U][]
- an array of tuples - an array of pairs - a dynamic sequential collection of pairs.
That's the approach I sincerely recommend. It's much easier to understand, and probably, to maintain.
Irrelevant tidbits
Ok so the statement "arrays are a homogenous collection, in type theory" is a bit of a lie. But it's only a lie in good faith. See, heterogenous, well-typed arrays exist - in highly advanced type systems. They are.....difficult to tame though, and honestly irrelevant in the context of typescript. But you know, in case someone finds this stuff interesting, here's Haskell with generalized algebraic data types and type families.
Jeez those are some difficult names.
I admittedly didn't know about any of this when I made the comments here, that was quite a few months ago. I had too much fun with Haskell in the meantime :)