Arrays of Objects in TypeScript: A Complete Guide with Examples

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Arrays of Objects in TypeScript: A Step-by-Step Tutorial for Those Tired of Errors

\n\n

Have you ever written TypeScript and suddenly gotten a red underline from your IDE when trying to add an object to an array? Sounds familiar, right? The question "How can I define an array of objects?" is one of the most popular on Stack Overflow. And for good reason: without proper typing of object arrays, your code turns into a source of bugs and headaches.

\n\n

In this tutorial, we'll cover all the ways to define an array of objects in TypeScript — from simple to advanced. You'll learn how to avoid common mistakes, how to use interfaces, and how to make your code not only functional but also elegant. Let's go!

\n\n

Why doesn't just [] work?

\n\n

Let's say you write:

\n\n
let users = [];
\n\n

TypeScript sees this as never[] — an array that should never contain any elements. Try adding an object to it:

\n\n
users.push({ name: 'Anna', age: 25 }); // Error!
\n\n

The IDE will scream: "Argument of type '{ name: string; age: number; }' is not assignable to parameter of type 'never'." TypeScript doesn't know what you intend to store in the array, so it blocks any additions.

\n\n

The solution is to explicitly specify the array type. Let's go through all the options.

\n\n

Method 1: Basic Type Annotation — Square Brackets

\n\n

The simplest and most intuitive way is to use the Type[] syntax:

\n\n
let users: { name: string; age: number }[] = [];\n\nusers.push({ name: 'Anna', age: 25 }); // ✅ Works\nusers.push({ name: 'Ivan', age: 30 }); // ✅ Works\n
\n\n

Here we tell TypeScript: "Hey, this is an array of objects, each of which has properties name (string) and age (number)". The IDE is now happy, autocomplete works, and type errors are caught at compile time.

\n\n

Downside: if the object structure is complex, describing it directly in the annotation becomes cumbersome. For such cases, interfaces were invented.

\n\n

Method 2: Interfaces — Your Best Friend

\n\n

Interfaces allow you to extract the object description into a separate entity and reuse it. This makes the code cleaner and more understandable:

\n\n
interface User {\n  id: number;\n  name: string;\n  age: number;\n  email?: string; // optional property\n}\n\nlet users: User[] = [];\n\nusers.push({ id: 1, name: 'Anna', age: 25 });\nusers.push({ id: 2, name: 'Ivan', age: 30, email: 'ivan@example.com' }); // ✅\n
\n\n

Now if you try to add an object without the id field or with the wrong type, TypeScript will throw an error. Interfaces are especially useful when the same object type is used in multiple places.

\n\n

What about type?

\n\n

Instead of interface, you can use type:

\n\n
type User = {\n  id: number;\n  name: string;\n  age: number;\n};\n\nlet users: User[] = [];
\n\n

The difference between interface and type is a topic for another article. For arrays of objects, you can use both options, but interface is more commonly used for describing object shapes.

\n\n

Method 3: Generic Syntax Array<Type>

\n\n

An alternative way is to use generics:

\n\n
let users: Array<{ name: string; age: number }> = [];\n\n// Or with an interface:\nlet users: Array<User> = [];\n
\n\n

Both syntaxes (Type[] and Array<Type>) work the same way. The choice is a matter of taste and context. Personally, I prefer Type[] for simple types and Array<Type> for complex generic constructs. But the main thing is to be consistent within the project.

\n\n

Method 4: Creating an Array with Initial Objects

\n\n

Often you need not just to declare an array but also to immediately populate it with data. TypeScr

Blogs

Book Recommendations