Typing Arrays in TypeScript

TypeScript Tagged in TypeScript Jan 14, 2018 3 mins read by Todd Motto

There are many ways we can type a property to declare to TypeScript something is an array, or contains an array of “something”. We have generic types, array types and type assertions.

For the purposes of this article, we’ll simply use a TypeScript class to demonstrate how we can declare some of these properties, in the various forms.

Type Inference

Before we explore the benefits of explicit typing, let’s consider a class with an array. This will infer the type of an array:

// inferred as messages: any[]
class Chats {
  messages = [];
}

And we can again, infer:

// inferred as messages: number[]
class Chats {
  messages = [1, 2, 3];
}

We can of course mix and match our types, and TypeScript will infer as best as possible:

// inferred as messages: (string | number)[]
class Chats {
  messages = ['A', 'B', 1, 2];
}

This is great for well defined APIs, return statements and such that we are fully confident we want to infer. So let’s explore the main ways we can type an array in TypeScript.

Declaring an Array Type

Before we continue, let’s introduce a second class member, the single Message:

class Message {
  constructor(private sender: string, private message: string) {}
}

// create a new message
new Message('Todd Motto', 'Hey, you around?');

Our Chats class can now be sensibly typed like so:

class Chats {
  messages: Message[] = [];
}

We assign what looks like an array, but we know it’s a type as we’re using : before the array assignment. Interestingly, outside of the array [] type, we specify what the array contains, i.e. Message[].

Learn more about using Classes as Types here!

In this case, we’re expecting only an array of messages.

We could in fact just declare the properties on the class, and assign the property’s value perhaps in the constructor.

class Chats {
  messages: Message[];

  constructor() {
    this.messages = [];
  }
}

In Angular, this is typically done inside the ngOnInit lifecycle hook:

class Chats implements OnInit {
  messages$: Observable<Message[]>;

  constructor(private store: Store<State>) {}

  ngOnInit() {
    this.messages$ = this.store.select('messages');
  }
}

A more comprehensive example, but we digress. However - you may have noticed Observable<Message[]>. Have you seen this before? If not, let’s explain because the same principle applies when typing arrays.

Angular Online Courses Angular shields
Ultimate Angular

Learn Angular the right way

Join my online courses to fully master Angular, TypeScript and NGRX.

Explore Courses Navigation arrow

Using Array Generic Types

Generic types in TypeScript are essentially ways to make things more… generic.

Generics are parameterised types, where we can either let TypeScript infer the type for us, or we can specify it ourselves. Using a generic type in TypeScript alongside an array looks like this (which is the equivalent to what we’ve covered above):

class Chats {
  messages: Array<Message> = [];
}

There’s no functional difference between using a generic instead of a normal typing, however depending on your use case and complexity of types - you may wish to opt for one over the other.

Another nice thing about generics is that we can combine initialisation and also infer the type, creating a new array whilst passing the generic type:

// inferred as messages: Message[]
class Chats {
  messages = new Array<Message>();
}

So, why do we have multiple ways to declare an array? TypeScript is pretty wild at times, and we have many ways to do things - TypeScript provides us a lot of options alongside that.

There are actually a few more ways to type an array as well (but I’d stick with the things we’ve covered above for sanity):

// I'd go for this option
class Chats {
  messages: Message[] = [];
}

// Looks a little more oldschool, but same as above
class Chats {
  messages: Array<Message> = new Array();
}

// Don't do this unless you need to assert the type
class Chats {
  messages = [] as Message[];
}

// And really, don't do this
class Chats {
  messages = <Array<Message>>[];
}

As the saying goes, “A typed array keeps the errors away”…

Okay that was terrible. Be smart, type your code and enjoy!

Angular Online Courses Angular shields
Ultimate Angular

Learn Angular the right way

Join my online courses to fully master Angular, TypeScript and NGRX.

Explore Courses Navigation arrow