TypeScript: Arrays and Tuples
Tags: typescript
Published: 2020-05-24 14:16:05

Working with arrays in TypeScript does not differ much compared with JavaScript. The same basic principles and methods apply, like iterations, filter, reduce, push, pull and etc. The main difference in TS is the restriction of what data types we would like to have in an array. For example, if we annotate that array should include only strings, we will get an error message if we try to push a number to the same array.

## Inference and Annotations

Inference system works great for arrays as well. If an array is filled with values, the corresponding types will be assigned automatically, and manual annotations are not needed. In the example below an array includes primitive string types. When hovering over the variable, an annotation with correct types is seen:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/4aqw05bq9ia8pwj88f5y.png)

If you wonder why do we need to annotate manually if the inference system works so well? One of the cases is when we need to initialize an array before we push values in it. When declaring an empty array, the inference doesn't know what data type values will be added in the future, so it assigns error-prone `any[]` type:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/5iferspnhrk9swwja6bu.png)

## Syntax

The annotation syntax for array is a value type followed by brackets `: Type[]`. Here's some examples of arrays with different value types:

```ts
// primitive types
const arrayOfStrings: string[] = []; // ['apple', 'pear']
const arrayOfNumbers: number[] = []; // [1, 2, 3]
const arrayOfBooleans: boolean[] = []; // [true, false]


// object types
const arrayObjects: { name: string }[] = []; // [{ name: 'John' }]
const arrayOfArrays: string[][] = []; // [['apple'], ['pear']]
const arrayOfDates: Date[] = []; // [new Date()];

// multiple values
// ['apple', 133, false];
const arrayOfPrimitiveMix: (string | number | boolean)[] = []; 

// [{ name: 'John'}, [133]]
const arrayOfObjectMix: ({ name: string } | number[])[] = [];
```

When an array is restricted to a certain type of values, an error message will be thrown if trying to assign different type:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/r429ttzogewj687ai6n2.png)

When working with array methods like map, filter or reduce, you gain an advantage of type inference and autocomplete. If we map through an array of strings, then each array element in the function will be assigned to string and get autocomplete for a full list of String properties.

## Tuples

It is a TypeScript feature that lets you restrict an array to a specific amount and type of values. It has a signature of `: [Type]` that slightly differs from an array `: Type[]`.
Let's express an array to be a tuple of string and number:
```ts
const myTuple: [string, number] = ['John', 30];
```
This tuple will always have a fixed amount of values of two, and order for a string to come first and number the second. If you mix the order of types or add a different amount of values, TS will throw an error.

Tuples are hard to understand. When you read code and see a tuple of a string and a number, you don't see a context for them. For example, in a tuple `['John', 30]` you can guess that the first value probably represents a name, but what does `30` represent? It can be a weight or a foot size. So for context purposes, it is better to use an object: `{ name: 'John', age: 30 }`.
There are special cases for Tuples. For example when working with CSV files. To represent a row entry it is convenient to use Tuples.

# Summing up

Expressing an array with known values, manual annotations are not needed, the inference system will do just fine. On the other hand, if values for an array are unknown, defining value types will make your development less error-prone.