Объекты и простые интерфейсы
Урок: Объекты и простые интерфейсы в TypeScript
Введение
До этого момента мы работали с простыми данными:
- строками (
string); - числами (
number); - булевыми значениями (
boolean); - функциями.
Но в реальной разработке почти всегда приходится работать не с отдельными значениями, а с наборами данных.
Например:
- пользователь (имя, возраст, email);
- товар (название, цена, наличие);
- настройки (флаги, параметры).
В JavaScript для этого используются объекты. Но без типизации они могут быть непредсказуемыми.
TypeScript решает эту проблему — он позволяет описывать структуру объектов.
Главная идея урока: мы учимся описывать форму объектов и делать их предсказуемыми с помощью типов и интерфейсов.
Типизация объектов напрямую
Начнём с простого объекта.
const user: { name: string; age: number } = {
name: 'Alex',
age: 30,
};
Что здесь происходит:
- мы явно описали структуру объекта;
nameдолжен быть строкой;age— числом.
Если попытаться сделать ошибку, TypeScript подсветит её до запуска:
// const badUser: { name: string; age: number } = {
// name: 'Alex',
// age: '30', // ошибка TS: age должен быть number
// };
const user: { name: string; age: number } = { name: 'Alex', age: 30 };
console.log('корректный пользователь:', user.name, user.age);
Почему такой способ неудобен
На первый взгляд всё работает, но есть проблема.
Если у тебя много объектов с одинаковой структурой:
const user1: { name: string; age: number } = { name: 'Alex', age: 30 };
const user2: { name: string; age: number } = { name: 'Bob', age: 25 };
Ты начинаешь:
- повторять один и тот же тип;
- усложнять код;
- увеличивать шанс ошибки.
Здесь и появляются интерфейсы.
Что такое интерфейс
Интерфейс — это способ задать «шаблон» для объекта.
interface User {
name: string;
age: number;
}
console.log(
'Интерфейс существует только на этапе проверки TS; в рантайме остаётся обычный объект с полями name и age.',
);
Теперь можно использовать его:
interface User {
name: string;
age: number;
}
const user: User = {
name: 'Alex',
age: 30,
};
console.log(user.name, user.age);
Что изменилось:
- структура описана один раз;
- код стал чище;
- легче поддерживать.
Как работает интерфейс
Интерфейс не создаёт объект. Он только описывает, каким должен быть объект.
TypeScript проверяет:
- есть ли все нужные поля;
- совпадают ли типы.
Пример ошибки (в реальном файле такой объект не пройдёт проверку):
interface User {
name: string;
age: number;
}
// const user: User = {
// name: 'Alex',
// // age отсутствует — ошибка TS
// };
const user: User = { name: 'Alex', age: 30 };
console.log('обязательные поля заполнены:', user);
Или неверный тип поля:
interface User {
name: string;
age: number;
}
// const user: User = {
// name: 'Alex',
// age: '30', // ошибка TS: age — number
// };
const user: User = { name: 'Alex', age: 30 };
console.log('age — число:', user.age);
Дополнительные свойства объекта
TypeScript строго проверяет структуру.
interface User {
name: string;
age: number;
}
// const user: User = {
// name: 'Alex',
// age: 30,
// isAdmin: true, // ошибка TS: лишнее поле при явном типе User
// };
const user: User = { name: 'Alex', age: 30 };
console.log('только поля из интерфейса:', user);
Почему это важно:
- предотвращает случайные ошибки;
- не даёт «засорять» объект лишними данными.
Необязательные свойства
Иногда не все поля обязательны.
Например:
- у пользователя может быть email, а может и не быть.
Для этого используется ?.
interface User {
name: string;
age: number;
email?: string;
}
const withEmail: User = { name: 'Bob', age: 25, email: 'bob@example.com' };
const withoutEmail: User = { name: 'Alex', age: 30 };
console.log('с email:', withEmail.email, '| без email:', withoutEmail.email);
Теперь:
interface User {
name: string;
age: number;
email?: string;
}
const user1: User = {
name: 'Alex',
age: 30,
};
const user2: User = {
name: 'Bob',
age: 25,
email: 'bob@example.com',
};
console.log(user1.name, user2.email);
Поле email:
- может быть;
- может отсутствовать;
- но если есть — должно быть строкой.
Использование объектов в функциях
Интерфейсы особенно полезны в функциях.
interface User {
name: string;
age: number;
}
function printUser(user: User) {
console.log(user.name + ' is ' + user.age);
}
printUser({ name: 'Alex', age: 30 });
// printUser({ name: 'Alex' }); // ошибка TS: не хватает age
TypeScript контролирует структуру переданных данных.
Вложенные объекты (базовое понимание)
Объекты могут содержать другие объекты.
Пример использования:
interface Address {
city: string;
}
interface UserWithAddress {
name: string;
address: Address;
}
const user: UserWithAddress = {
name: 'Alex',
address: {
city: 'Helsinki',
},
};
console.log(user.address.city);
TypeScript проверяет структуру на всех уровнях.
Связь с дальнейшими уроками
Этот урок — очень важный шаг.
Мы перешли от:
- отдельных значений к
- структурированным данным.
Дальше мы:
- научимся точно задавать, что возвращают функции;
- будем использовать интерфейсы вместе с функциями;
- применим это в Playwright (page, locator, test);
- и в итоге — в Page Object.
Практическое применение
Интерфейсы используются почти везде:
- данные пользователя;
- ответы API;
- настройки;
- структуры тестов.
Пример из реальной задачи:
interface LoginPayload {
username: string;
}
function login(data: LoginPayload): void {
console.log(data.username);
}
login({ username: 'admin' });
Это:
- делает код понятным;
- упрощает работу в команде;
- снижает количество ошибок.
Итоговое понимание
Объекты — это способ хранить связанные данные. Интерфейсы — это способ сделать эти данные понятными и контролируемыми.
Главная идея урока:
TypeScript позволяет описать форму объекта один раз и затем использовать её везде, гарантируя, что данные всегда соответствуют ожиданиям.
Именно интерфейсы становятся основой для более сложных структур — включая Page Object, с которым мы будем работать дальше.