Array Types

Typing arrays and the elements inside of them

Note: Arrays are also sometimes used as tuples in JavaScript, these are annotated differently in Flow. See the Tuple docs for more information.

Arrays are a special list-like type of object in JavaScript. You can create arrays a couple different ways.

1
2
3
new Array(1, 2, 3); // [1, 2, 3];
new Array(3);       // [undefined, undefined, undefined]
[1, 2, 3];          // [1, 2, 3];

You can also create arrays and add values to them later on:

1
2
3
4
let arr = []; // []
arr[0] = 1;   // [1]
arr[1] = 2;   // [1, 2]
arr[2] = 3;   // [1, 2, 3]

Array Type

To create an array type you can use Array<Type> type where Type is the type of elements in the array. For example, to create a type for an array of numbers you use Array<number>.

1
let arr: Array<number> = [1, 2, 3];

You can put any type within Array<Type>.

1
2
3
let arr1: Array<boolean> = [true, false, true];
let arr2: Array<string> = ["A", "B", "C"];
let arr3: Array<mixed> = [1, true, "three"]

Array Type Shorthand Syntax

There’s also a slightly shorter form of this syntax: Type[].

1
let arr: number[] = [0, 1, 2, 3];

Just note that ?Type[] is the equivalent of ?Array<T> and not Array<?T>.

1
2
3
4
// @flow
let arr1: ?number[] = null;   // Works!
let arr2: ?number[] = [1, 2]; // Works!
let arr3: ?number[] = [null]; // Error!
array literal Has some incompatible type argument with array type

If you want to make it Array<?T> you can use parenthesis like: (?Type)[]

1
2
3
4
// @flow
let arr1: (?number)[] = null;   // Error!
let arr2: (?number)[] = [1, 2]; // Works!
let arr3: (?number)[] = [null]; // Works!
null This type is incompatible with array type

Array access is unsafe

When you retrieve an element from an array there is always a possibility that it is undefined. You could have either accessed an index which is out of the bounds of the array, or the element could not exist because it is a “sparse array”.

For example, you could be accessing an element that is out of the bounds of the array.

1
2
3
4
// @flow
let array: Array<number> = [0, 1, 2];
let value: number = array[3]; // Works.
                       // ^ undefined

Or you could be accessing an element that does not exist if it is a “sparse array”.

1
2
3
4
5
6
7
8
// @flow
let array: Array<number> = [];

array[0] = 0;
array[2] = 2;

let value: number = array[1]; // Works.
                       // ^ undefined

In order to make this safe, Flow would have to mark every single array access as “possibly undefined”.

Flow does not do this because it would be extremely inconvenient to use. You would be forced to refine the type of every value you get when accessing an array.

1
2
3
4
5
6
let array: Array<number> = [0, 1, 2];
let value: number | void = array[1];

if (value !== undefined) {
  // number
}

As Flow is made to be smarter it may be possible in the future to fix this problem, but for now you should be aware of it.


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