2

Does anybody know how to make compiler to infer tuple type automatically ?

// Now: (string | number)[]
// Wanted: [string, number][]
const x = [ ["a", 2], ["b", 2] ];
NN_
  • 1,473
  • 1
  • 10
  • 24
  • 1
    it doesn't look like it can, it can't assume that the inner arrays will always be of the same length. You have to specify that yourself – toskv Feb 19 '18 at 18:49

2 Answers2

2

This can be done if we use an extra function to help type inference a bit:

function tupleArray<T1, T2, T3>(arr:[T1, T2, T3][]) : typeof arr 
function tupleArray<T1, T2>(arr:[T1, T2][]) : typeof arr 
function tupleArray<T1>(arr:[T1][]) : typeof arr 
function tupleArray(arr:any[]) : any[]{
    return arr;
}

var t = tupleArray([ ["a", 2], ["b", 2] ]) // [string, number][]

Edit

Better version with fewer overrides:

const tupleArray = <T extends ([any] | any[])[]>(args: T): T => args
tupleArray([["A", 1], ["B", 2]]) // [string, number][]

You can add more overloads if you need more then 3 items in the tuple.

Titian Cernicova-Dragomir
  • 157,784
  • 15
  • 245
  • 242
0

The compiler does not infer that, and there no way to force it to "know" it. the only thing that you can (And should do) is defined an interface that extends Array. like this:

interface NumStrTuple extends Array<string | number> {
    0: number;
    1: string;
    length: 2;
}

And use it to define your const like this:

const x: NumStrTuple = [ ["a", 2], ["b", 2] ];
gilamran
  • 5,914
  • 4
  • 27
  • 48