Короткий ответ: чтобы типизировать объект в TypeScript, опишите его форму через type или interface, а затем примените этот тип к переменной, параметру функции или возвращаемому значению
Пример:
type User = {
id: number;
email: string;
isActive: boolean;
};
const user: User = {
id: 1,
email: "user@example.com",
isActive: true,
};
Теперь TypeScript знает, какие поля должны быть у user и какого они типа
type или interface
Через interface:
interface Product {
id: number;
title: string;
price: number;
}
Через type:
type Product = {
id: number;
title: string;
price: number;
};
Для обычного объекта можно использовать любой вариант. Важно не название инструмента, а ясность формы объекта
Необязательные поля
Если поле может отсутствовать:
type Article = {
id: number;
title: string;
description?: string;
};
При использовании нужно учитывать, что description может быть undefined:
if (article.description) {
console.log(article.description.toUpperCase());
}
Ограничить значения поля
Для статусов используйте union:
type Order = {
id: number;
status: "new" | "paid" | "cancelled";
};
Теперь нельзя случайно записать:
const order: Order = {
id: 1,
status: "done",
};
TypeScript покажет ошибку
Вложенный объект
type UserProfile = {
id: number;
name: string;
address: {
city: string;
street: string;
};
};
Если вложенный объект используется в нескольких местах, лучше вынести его отдельно:
type Address = {
city: string;
street: string;
};
type UserProfile = {
id: number;
name: string;
address: Address;
};
Когда нужен Record
Если объект похож на словарь:
type Prices = Record<string, number>;
const prices: Prices = {
book: 900,
course: 4900,
};
Record<string, number> означает: ключи — строки, значения — числа
Типизация параметра функции
Часто объект нужно типизировать не у переменной, а у аргумента:
type CreateUserInput = {
email: string;
password: string;
name?: string;
};
function createUser(input: CreateUserInput) {
return {
id: crypto.randomUUID(),
email: input.email,
name: input.name ?? "Без имени",
};
}
Теперь TypeScript проверяет вызов:
createUser({
email: "user@example.com",
password: "secret",
});
Если забыть password, ошибка появится до запуска кода
Тип результата функции
Иногда полезно явно описать результат:
type User = {
id: string;
email: string;
name: string;
};
function createUser(input: CreateUserInput): User {
return {
id: crypto.randomUUID(),
email: input.email,
name: input.name ?? "Без имени",
};
}
Так функция не сможет случайно вернуть объект без id или email
Частые ошибки
Первая ошибка — писать object. Такой тип запрещает доступ к конкретным полям:
const user: object = { id: 1 };
TypeScript не будет знать, что у объекта есть id
Вторая ошибка — использовать any. Так ошибка исчезает, но проверка типов тоже исчезает
Третья ошибка — делать все поля необязательными без причины. Тогда TypeScript не сможет гарантировать, что объект действительно готов к работе
Четвертая ошибка — использовать один огромный тип объекта для всех сценариев. Для создания, обновления и ответа API часто нужны разные типы: CreateUserInput, UpdateUserInput, UserDto
Самопроверка
Опишите тип Task с полями id, title, done. Создайте объект без title и убедитесь, что TypeScript ругается. Потом сделайте description?: string и проверьте, что это поле можно не указывать
Что почитать дальше по TypeScript
Если нужен общий маршрут по теме, откройте рубрику TypeScript. Для соседних задач пригодятся эти разборы:
- TypeScript Map: как типизировать ключи и значения
- TypeScript функция как аргумент: как типизировать callback
- Как типизировать массив объектов в TypeScript
- Стоит ли использовать TypeScript: честный разбор