Tuple Types

Typing tuple-like array values

Tuples are a sort of list but with a limited set of items. In JavaScript, tuples are created using arrays.

In Flow you can create tuples using the [type, type, type] syntax.

1
2
3
let tuple1: [number] = [1];
let tuple2: [number, boolean] = [1, true];
let tuple3: [number, boolean, string] = [1, true, "three"];

When you are getting a value from a tuple at a specific index, it will return the type at that index.

1
2
3
4
5
6
// @flow
let tuple: [number, boolean, string] = [1, true, "three"];

let num  : number  = tuple[0]; // Works!
let bool : boolean = tuple[1]; // Works!
let str  : string  = tuple[2]; // Works!

If you try getting from an index that does not exist it will return a type of void.

1
2
3
4
// @flow
let tuple: [number, boolean, string] = [1, true, "three"];

let none: void = tuple[3];
access of computed property/element Out of bound access. This tuple has 3 elements and you tried to access index 3 of tuple type

If Flow doesn’t know which index you are trying to access it will return all possible types.

1
2
3
4
5
6
7
// @flow
let tuple: [number, boolean, string] = [1, true, "three"];

function getItem(n: number) {
  let val: number | boolean | string = tuple[n];
  // ...
}

When setting a new value inside a tuple, the new value must match the type at that index.

1
2
3
4
5
6
7
8
9
10
11
12
13
// @flow
let tuple: [number, boolean, string] = [1, true, "three"];

tuple[0] = 2;     // Works!
tuple[1] = false; // Works!
tuple[2] = "foo"; // Works!

// $ExpectError
tuple[0] = "bar"; // Error!
// $ExpectError
tuple[1] = 42;    // Error!
// $ExpectError
tuple[2] = false; // Error!
string This type is incompatible with number number This type is incompatible with boolean boolean This type is incompatible with string

Strictly enforced tuple length (arity)

The length of the tuple is known as the “arity”. The length of a tuple is strictly enforced in Flow.

Tuples only match tuples with same length

This means that a shorter tuple can’t be used in place of a longer one.

1
2
3
4
// @flow
let tuple1: [number, boolean]       = [1, true];
// $ExpectError
let tuple2: [number, boolean, void] = tuple1; // Error!
tuple type Tuple arity mismatch. This tuple has 2 elements and cannot flow to the 3 elements of tuple type

Also, a longer tuple can’t be used in place of a shorter one.

1
2
3
4
// @flow
let tuple1: [number, boolean, void] = [1, true];
// $ExpectError
let tuple2: [number, boolean]       = tuple1; // Error!
array literal Tuple arity mismatch. This tuple has 2 elements and cannot flow to the 3 elements of tuple type tuple type Tuple arity mismatch. This tuple has 3 elements and cannot flow to the 2 elements of tuple type
Tuples don’t match array types

Since Flow does not know the length of an array, an Array<T> type cannot be passed into a tuple.

1
2
3
4
// @flow
let array: Array<number>    = [1, 2];
// $ExpectError
let tuple: [number, number] = array; // Error!
array type Only tuples and array literals with known elements can flow to tuple type

Also a tuple type cannot be passed into to an Array<T> type, since then you could mutate the tuple in an unsafe way.

1
2
3
4
// @flow
let tuple: [number, number] = [1, 2];
// $ExpectError
let array: Array<number>    = tuple; // Error!
tuple type This type is incompatible with array type
Cannot use mutating array methods on tuples

You cannot use Array.prototype methods that mutate the tuple, only ones that do not.

1
2
3
4
5
// @flow
let tuple: [number, number] = [1, 2];
tuple.join(', '); // Works!
// $ExpectError
tuple.push(3);    // Error!
property `push` Property not found in $ReadOnlyArray

Was this guide helpful? Let us know by sending a message to @flowtype.