TypeScript Arrays for Beginners

Learn how to use type annotations to define TypeScript arrays in this step-by-step guide for beginners.

TypeScript Arrays for Beginners

Welcome! In this article, you will learn how to work TypeScript arrays using type annotations. You will find that they are actually quite similar to JavaScript arrays with a few powerful additions.

Let's begin! ๐Ÿ”…

TypeScript Arrays

Let's start by talking about arrays in general and what they are in TypeScript.

What are TypeScript Arrays?

Arrays are built-in data structures that can store multiple values. TypeScript arrays are very similar to the arrays that we usually work with in JavaScript.

Arrays are very versatile. We can modify, expand, and shrink them as needed. We can add or remove elements and the length of the array will be updated automatically. We can also update existing elements.

They are used to store sequences of related values. For example, we could store a list of names, a list of products that will be shipped, or a list of customers who made a purchase.

Data Types

The key characteristic of arrays is that they store related values and related values are usually of the same data type, right?

This is where TypeScript becomes a bit more strict than JavaScript. You can specify the data type of the values that the array can store. If you try to add a value of a different data type while the program is running, you will get an error.

๐Ÿ’ก
If you do not state the data type of the values explicitly, TypeScript will infer the data type. The selected data type will be the data type of the initial values in the array.

That is the magic of static typing in TypeScript and in just a moment we will see the advantages of this helpful feature.

TypeScript Arrays vs. JavaScript Arrays

These are the key differences between arrays in TypeScript and JavaScript:

  • TypeScript arrays are statically typed whereas JavaScript arrays are not typed.

  • TypeScript arrays can only contain elements of the specified data type whereas JavaScript arrays can contain elements of any data type.

  • The TypeScript compiler checks if the data types of all the elements in the array are compatible at compile-time whereas JavaScript finds and shows errors at runtime (while the code is running).

Why is Static Typing Important for Arrays?

By ensuring that all the elements of the array are of a specific data type (or data types), we can find and fix potential errors early in the development process. We may even find a potential bug before running the program.

That sounds very helpful, right?

Explicitly stating the data type of the values of an array can also make your code much easier to read and understand. You and other developers who are reading your code will be able to identify this and know how to work with the arrays in your code.

This can be especially helpful in complex projects with many files and folders.

๐Ÿ’ก
In TypeScript, you can also define custom types and use them in the arrays to store objects of these custom types. For example, you could define a Product type with the properties of a product. Each property would have its own data type and the compiler would check if all the elements in the array are of this custom type.

Static Typing of TypeScript Arrays

Great. Now that you know more about the "theoretical" aspects of TypeScript arrays and why they are helpful, let's dive into the practical aspects and their syntax.

We will answer this question:

How can you define an array in TypeScript using type annotations?

Are you ready? Let's continue. โœจ

Type Annotations for One-Dimensional Arrays

It's very easy to define a one-dimensional array in TypeScript. You just need to add this next to the name of the variable that will store the array:

:<dataType>[]

Notice the syntax:

  • A colon (:).

  • The data type of the elements in the array. <dataType> can be any built-in data type in TypeScript or a custom type defined in your program.

  • An empty pair of square brackets [].

๐Ÿ’ก
To find more information on the built-in data types that you can work with in TypeScript, I recommend checking out my article on Type Annotations.

This type annotation must be after the name of the variable that will store the array and before the assignment operator, like this:

let products: string[] = ["Laptop", "Keyboard", "Headphones"];

In this example, we are defining an array of strings.

The syntax is very similar to defining an array in JavaScript. We just add the type annotation after the name.

Here we have an example with numbers:

let grades: number[] = [56, 23, 78, 23];

And here we have an array of boolean values:

let hasGreenEyes: boolean[] = [true, false, true, true, false];
๐Ÿ’ก
You can also create arrays within arrays. We will see how you can do this in just a moment.

Mismatched Types

This looks great, right? But does it work in practice?

Will you see an error if the data types do not match?

๐Ÿ’ก Let's see...

To see the magic of TypeScript in action, try to assign an array with elements of a data type that does not match the type annotation.

If you do this...

You will see an error! ๐Ÿšง

This is an example where we are trying to assign an array of numbers to a variable annotated as an array of strings:

To fix this, just update the type annotation to number[] and the error will be gone.

let numbers: number[] = [4, 5, 2, 2];
๐Ÿ’ก
You should also update the name of the variable to be more descriptive of what they array represents (in this case, a sequence of numbers).

Type Annotations for Empty Arrays

What type annotation should you use for an empty array?

That's a great question because... they are empty. ๐Ÿ˜…

Since empty arrays do not have any values (yet!), they are compatible with any data type, so you can use any valid type annotation for an array.

let myArray: string[] = [];
let myArray: number[] = [];
let myArray: boolean[] = [];

These three examples are valid lines of code.

The data type of the values that you will add to the empty array later on while the program is running must match the data type in the annotation. Otherwise, you will see an error if the types do not match.

Type Annotations for Multidimensional Arrays

Now let's talk about multidimensional arrays (arrays within arrays).

๐Ÿ’ก
The most commonly used type of multidimensional array is the two-dimensional array, so we will focus on this in this article. The same principles apply for higher dimensions.

How can you write a type annotation for a multidimensional array?

You only need to add a very simple thing to the syntax that you just learned: an empty pair of square brackets.

:<dataType>[][]

Yes, that's right. This extra pair of square brackets tells TypeScript that this will be an array that will contain arrays with elements of this data type.

Let's compare the type annotations:

// One-dimensional array.
:<dataType>[] 
// Two-dimensional array. 
:<dataType>[][] // Extra []!

Behind the scenes, this annotation is equivalent to this:

// An array that contains arrays with elements of this data type.
(<dataType>[])[]

Here we have an example:

let products: string[][] = [["Laptop", "1420"], ["Tablet", "159"]];

We have an array that contains subarrays of strings.

๐Ÿ’ก
string[][] is equivalent to (string[])[]. First, we have an array when we write ()[] and then, within the parentheses, we specify the data type of the elements contained within the nested arrays (strings).

Array Type Inference

One of the amazing things about TypeScript is that it's also very "smart". It can infer the data type of a variable without even writing the type annotation explicitly. This process is called "type inference".

For example, let's say that you define this array without writing a type annotation:

let myArray = ["Nora", "Gino", "Lulu"];

If you hover over the name of the variable in your code editor, you will see that the type was inferred to be string[] (an array of strings):

Amazing, right? ๐Ÿ˜ TypeScript just guesses the correct data type based on the initial value we assigned to the variable.

This will automatically protect our array from unexpected changes that may result in a type mismatch.

As an example, if we try to add a number to an array of strings, we will see an error like this one:

That is the power of type inference in TypeScript in the context of arrays.

Union Types for Arrays

But what if you need to have multiple values of different data types in the same array? TypeScript also has a great feature for this: union types.

Union types give you more flexibility on the data types that are allowed in the array. As their name implies, they are a union of multiple data types.

๐Ÿ’ก
You can write a union type anywhere where you can write a simpler type annotation. We will talk about union types in more depth in this series. This is a brief introduction.

You can use a union type to allow two or more data types in the same array.

This is the syntax for specifying a union type for an array:

: (dataType1 | dataType2)[]

For example, here we have an array that can store both strings and numbers:

let myArray: (string | number)[] = ["Nora", "Gino", 10, 15];

In this new type annotation:

  • The data types are written in parentheses ().

  • They must be separated by a vertical bar |.

  • There should be an empty pair of square brackets [] after the parentheses.

๐Ÿ’ก
To make your code easier to read and understand, it's recommended to add a space before and after the vertical bar (between the data types).

Recommended:

// Space between the data types.
let myArray: (string | number)[] = ["Nora", "Gino", 10, 15];

Not recommended:

// No space between the data types.
let myArray: (string|number)[] = ["Nora", "Gino", 10, 15];

Important Difference

It's very important to note that:

(string | number)[]

is not the same as:

string | number[]

Even though they may look similar at first, they do have very different meanings.

(string | number)[] is an array that can store either strings or numbers. This would be a valid array of this union type:

let myArray: (string | number)[] = ["Nora", "Gino", 10, 15];
๐Ÿ’ก
The array could also contain all strings or all numbers. But this union type gives you the flexibility to combine them.

string | number[] is either a string or an array of numbers. These would be valid lines of code for this union type:

let myArray: string | number[] = [1, 2, 3, 4];
let myArray: string | number[] = "Hello, World!";

It's very important to keep this in mind when you are writing union types. These small differences can have a huge impact on your code.

Object Types for Arrays of Objects

In TypeScript, we can also create custom data types. This is especially helpful for working with objects because we can specify the data types of their properties.

Syntax

This is the syntax for defining an object type:

type TypeName = {property1: type1, property2: type2, ...};

From left to right, we write:

  • The keyword type.

  • The name of the custom type. We will use this in our type annotations.

  • The assignment operator =.

  • An object that defines the properties of this type of object and the data type of each property. The keys are the properties and the values are their corresponding data types.

  • A semicolon at the end ;.

Object Type Example

Let's say that we are developing an e-commerce platform.

We may represent a product with a custom type. The product will have a description (string) and a price (number):

type Product = {description: string, price: number};

To define this custom type, we write (from left to right):

  • The type keyword.

  • The name of the type alias (Product).

  • The assignment operator.

  • An object that describes the "structure" of the objects of that type. The description is a string and the price is a number. All objects of this type must follow these rules.

  • A semicolon at the end.

Then, once you have the custom type defined in your program, you can use it in any type annotation.

Array of Objects Example

We can create an array of objects of the custom type Product:

// Notice the type annotation below (Product[]).
let myArray: Product[] = [
    {
        description: "Laptop",
        price: 2300
    },
    {
        description: "Tablet",
        price: 150
    }
];

We write the type annotation after the name of the variable myArray.

This is the full code with the custom type definition and an example of how to assign it to a variable:

type Product = {description: string, price: number};

let myArray: Product[] = [
    {
        description: "Laptop",
        price: 2300
    },
    {
        description: "Tablet",
        price: 150
    }
];
๐Ÿ’ก
Note how the objects in the array match the structure and data types of the custom type. They all have a "description" property, which is a string and they all have a "price" property, which is a number. If an object in the array does not follow the rules, you will see an error.

Object Types in Union Types

You can also use custom object types in union types.

For example, in this array, we can store either strings or objects of type Products. If the values match either one of these types, the array will be valid.

type Product = {description: string, price: number};

let myArray: (string | Product)[] = [
    {
        description: "Laptop",
        price: 2300
    },
    {
        description: "Tablet",
        price: 150
    },
    "Headphones" // A simple string.
];

Advantages of Static Typing for Arrays

Awesome. Now that you know more about arrays and type annotations in TypeScript, let's review static typing is helpful:

  • You can catch errors early, even before you run your code.

  • It can make your code more readable and maintainable because you and other developers will be able to identify the data type(s) more easily.

  • It can help you to write cleaner code that is less error-prone.

๐Ÿ’ก
Array operations in TypeScript work the same as they did in JavaScript with the one addition of static typing. You can call methods on the arrays but now the data types of the values must match the type annotations or you will see an error when transpiling your code into JavaScript.

Conclusion

  • TypeScript uses static typing to make sure that your variables and data structures store values of the data types that you originally intended.

  • Arrays in TypeScript are very similar to arrays in JavaScript with the addition of type annotations. You can use type annotations with one-dimensional and multi-dimensional arrays.

  • With union types, you can store values of different data types (that you specify) in the same array. They add more flexibility to the process of static typing.

  • You can define custom object types in your program and use them to create arrays of objects of these custom types.

Thanks for reading my article! Now you know more about how to work with arrays in TypeScript. To learn more about TypeScript, check out my series below.

If you would like to find more coding tutorials, follow me on YouTube (Coding with Estefania) and X (@EstefaniaCassN). Have an awesome day. ๐Ÿ”…

ย