Taming Arrays of Things
What's in this array?
Arrays in JavaScript are incredibly flexible. You can throw anything you want into them: strings, numbers, objects, all at the same time.
But this flexibility comes at a cost. When you loop over an array, what can you safely do with each element? If you have an array of product names, you'd expect to be able to call .toUpperCase()
on each one. But if a number accidentally slipped into that array, your code will crash at runtime.
const mixedBag = ["one", "two", 3, "four"];
mixedBag.forEach(item => {
console.log(item.toUpperCase()); // 💥 CRASH! .toUpperCase is not a function on number
});
TypeScript solves this by allowing you to declare what an array is allowed to contain.
Declaring Typed Arrays
The syntax is simple and intuitive. To declare an array that can only contain strings, you write string[]
. For an array of numbers, it's number[]
.
This simple annotation does two powerful things:
- It gives you type-aware autocomplete on the array's elements.
- It prevents you from accidentally adding the wrong type of data to the array.
Exercise 1: Type-Aware Autocomplete
- We've declared
ingredients
as an array of strings (string[]
). - Inside the
.map()
function, typeingredient.
and notice the autocomplete. You see all the string methods liketoUpperCase
,slice
, etc. - Complete the code to make all the ingredients uppercase.
Exercise 2: Preventing Mistakes
- In the code below, we have an array of numbers.
- Try to
.push()
a string into the array. - Notice that TypeScript immediately shows an error. You've just prevented a potential runtime bug.
- Fix the error by pushing a number instead.
How to Type an Array of Objects
This is where typing arrays really shines. It combines perfectly with the type
aliases we learned in the last lesson. If you have a User
type, you can declare an array of users like this: User[]
.
Exercise 3: Autocomplete on Objects in an Array
- We have a
User
type and an array ofusers
. - Inside the
.map()
function, theuser
parameter is now fully typed. - Type
user.
and see the magic. TypeScript knows it has anid
and aname
. - Complete the function to return an array of just the user names.
This is the payoff. You define your data structures once, and then TypeScript helps you use them correctly everywhere, including inside loops and array methods. No more guessing user.id
vs user.ID
, and no more typos on property names.
A Quick Note on Syntax: Array<T>
You might also see the syntax Array<string>
or Array<User>
. This is a "generic" syntax. It does the exact same thing as string[]
or User[]
. Which one you use is purely a matter of team preference. We'll cover generics in more detail later, but for now, just know that T[]
and Array<T>
are equivalent.