2

I was in need of proper tuple type inference in Typescript and stumbled upon a magic solution for my problem in the official Typescript GitHub.

In the following snippet, tuple3 is obviously the proposed solution. I have added some variations not leading to the expected result.

My question is: Why does tuple3 work like it does? I imagine union types working like an exclusive selection. Check, if the first type in the union fits, if so, use it, otherwise proceed to the next one. Following this rule, I would expect the compiler to find that (for tuple3) [void] doesn't fit the given argument for inference, so it uses {} as type, leading to the same result as tuple4. But apparently the types in the union ([void] | {}) are connected somehow? Is this a feature or a bug? Is it documented somewhere?

function tuple1<TupleT>(tuple: TupleT): TupleT
{ return tuple; }

tuple1([42, 'foo', true]); // type: (string | number | boolean)[]


function tuple2<TupleT extends [void]>(tuple: TupleT): TupleT
{ return tuple; }

tuple2([42, 'foo', true]); // error: [number, string, boolean] not assignable to [void]


function tuple3<TupleT extends [void] | {}>(tuple: TupleT): TupleT
{ return tuple; }

tuple3([42, 'foo', true]); // type: [number, string, boolean]


function tuple4<TupleT extends {}>(tuple: TupleT): TupleT
{ return tuple; }

tuple4([42, 'foo', true]); // type: (string | number | boolean)[]


function tuple5<TupleT extends [any]>(tuple: TupleT): TupleT
{ return tuple; }

tuple5([42, 'foo', true]); // error: [number, string, boolean] not assignable to [any]
2
  • 1
    I think the key is in the comment, "add a tuple-like constraint ". If the compiler sees the tuple constraint it will go into inferring tuples for array literals. Now obviously the tuples will not satisfy [void], but since T can be [void] | {} the tuples will satisfy {} but the [void] part put the compiler in the 'mood' to infer tuples. An interesting note is that this function will allow ANY object as an argument not just a tuple ! tuple3({ test : 'ss'}); works just fine. I would use a more conventional solution with multiple overloads.. Commented May 16, 2018 at 9:41
  • 1
    While not pretty this would be the overload solution: stackoverflow.com/questions/49729550/… Commented May 16, 2018 at 9:46

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.