When dealing with array literals, the type inference in TypeScript does not automatically infer tuples but rather infers arrays. For instance:
var foo = ["", 0]; // foo is Array<string | number> not [string, number]
While there isn't official documentation on this behavior, it seems deliberate based on a pull request that added tuple support without inference during declaration.
If you want to work with tuples specifically, you can specify the type parameter like so:
['List', 'Of', 'Names']
.map<[string, number]>((name, index) => [name, index % 2])
.map(([name, num]) => name + "");
Solution for TypeScript 2.9 and earlier
Alternatively, if you encounter this issue frequently, you can create a helper function for tuples:
function tuple<T1, T2, T3, T4, T5>(data: [T1, T2, T3, T4, T5]) : typeof data
function tuple<T1, T2, T3, T4>(data: [T1, T2, T3, T4]) : typeof data
function tuple<T1, T2, T3>(data: [T1, T2, T3]) : typeof data
function tuple<T1, T2>(data: [T1, T2]) : typeof data
function tuple(data: Array<any>){
return data;
}
['List', 'Of', 'Names']
.map((name, index) => tuple([name, index % 2]))
.map(([name, num]) => name + "");
Solution for TypeScript 3.0 and later
In recent versions of TypeScript, improvements have been made in tuple type inference, allowing us to use rest parameters effectively for tuples. This enables a more concise version of the tuple
function:
function tuple<T extends any[]> (...data: T){
return data;
}
['List', 'Of', 'Names']
.map((name, index) => tuple(name, index % 2))
.map(([name, num]) => name + "");