Короткий ответ: массив объектов в TypeScript типизируют через тип одного элемента. Сначала описывают объект, потом указывают массив таких объектов: Product[] или Array<Product>
Пример:
type Product = {
id: number;
title: string;
price: number;
inStock: boolean;
};
const products: Product[] = [
{ id: 1, title: "Книга", price: 900, inStock: true },
{ id: 2, title: "Курс", price: 4900, inStock: false },
];
Теперь TypeScript проверит каждый объект в массиве. Если забыть price или передать id строкой, появится ошибка
type или interface
Можно описать элемент через interface:
interface User {
id: number;
email: string;
role: "admin" | "client";
}
const users: User[] = [
{ id: 1, email: "admin@example.com", role: "admin" },
];
Для простого массива объектов подойдут оба варианта. type удобен для union-типов и композиций, interface часто используют для описания формы объекта
Необязательные поля
Если поле может отсутствовать, поставьте ?:
type Article = {
id: number;
title: string;
description?: string;
};
const articles: Article[] = [
{ id: 1, title: "TypeScript" },
{ id: 2, title: "React", description: "Практика" },
];
При чтении необязательного поля проверяйте его:
for (const article of articles) {
if (article.description) {
console.log(article.description.toUpperCase());
}
}
map и filter
TypeScript сохраняет типы при работе с массивом:
const availableProducts = products.filter((product) => product.inStock);
const titles = products.map((product) => product.title);
Если нужно преобразовать массив:
type ProductView = {
label: string;
value: number;
};
const views: ProductView[] = products.map((product) => ({
label: product.title,
value: product.price,
}));
Readonly-массив
Если функция не должна менять массив:
function printProducts(items: readonly Product[]) {
for (const item of items) {
console.log(item.title);
}
}
Теперь внутри функции нельзя сделать items.push(...). Это полезно для функций, которые только читают данные
Массив объектов из API
Часто массив приходит с сервера:
type UserDto = {
id: number;
email: string;
createdAt: string;
};
async function loadUsers(): Promise<UserDto[]> {
const response = await fetch("/api/users");
const data = await response.json();
return data as UserDto[];
}
Важно: as UserDto[] не проверяет данные в runtime. Это только подсказка TypeScript. Если API внешний или нестабильный, добавьте валидацию: проверьте, что data действительно массив, а у каждого элемента есть нужные поля
Минимальная ручная проверка:
function isUserDto(value: unknown): value is UserDto {
return (
typeof value === "object" &&
value !== null &&
typeof (value as UserDto).id === "number" &&
typeof (value as UserDto).email === "string"
);
}
После этого можно фильтровать:
const users = Array.isArray(data) ? data.filter(isUserDto) : [];
Частые ошибки
Первая ошибка — писать object[]. Такой тип почти ничего не говорит о полях. TypeScript не будет знать, что у объекта есть title или price
Вторая ошибка — использовать any[]. Это отключает проверку и превращает TypeScript обратно в JavaScript
Третья ошибка — описывать массив как один объект:
const products: Product = [];
Правильно:
const products: Product[] = [];
Четвертая ошибка — слепо доверять response.json(). TypeScript не знает, что реально пришло по сети. Типизируйте результат, но помните про runtime-проверку
Самопроверка
Добавьте в массив объект:
{ id: "3", title: "Ошибка", price: 100, inStock: true }
TypeScript должен подсказать, что id должен быть числом. Потом добавьте функцию, которая принимает readonly Product[], и попробуйте внутри сделать push. Ошибка подтвердит, что массив защищен от изменения
Что почитать дальше по TypeScript
Если нужен общий маршрут по теме, откройте рубрику TypeScript. Для соседних задач пригодятся эти разборы:
- Как типизировать массив объектов в TypeScript
- Create React App и TypeScript: как установить, запустить и проверить
- TypeScript npm: как установить, запустить и проверить
- TypeScript скачать: как установить, запустить и проверить