Пошук уроків, статей та іншого контенту
Створюємо інтерфейси для опису форми об’єктів, їхніх властивостей і методів у TypeScript.
Інтерфейс (interface) описує форму об’єкта: які властивості та методи він повинен мати, а також які типи даних вони використовують.
Інтерфейс не створює об’єкт і не містить даних. Він лише визначає правила для об’єктів.
interface User {
id: number;
name: string;
email: string;
}Тепер об’єкт типу User повинен мати властивості id, name та email із відповідними типами:
const user: User = {
id: 1,
name: "Олена",
email: "olena@example.com",
};Якщо пропустити обов’язкову властивість або вказати неправильний тип, TypeScript повідомить про помилку:
const user: User = {
id: 1,
name: "Олена",
// Помилка: відсутня обов’язкова властивість email
};const anotherUser: User = {
id: "1",
name: "Олена",
email: "olena@example.com",
// Помилка: id має бути числом
};В інтерфейсі можна описувати властивості різних типів:
interface Product {
name: string;
price: number;
inStock: boolean;
}Об’єкт цього типу:
const product: Product = {
name: "Клавіатура",
price: 2500,
inStock: true,
};Типи властивостей можуть бути складнішими:
interface Article {
title: string;
tags: string[];
author: {
name: string;
email: string;
};
}Приклад використання:
const article: Article = {
title: "Вивчаємо TypeScript",
tags: ["typescript", "javascript"],
author: {
name: "Іван",
email: "ivan@example.com",
},
};TypeScript перевіряє вкладені об’єкти так само, як і властивості верхнього рівня.
Знак питання після назви властивості робить її необов’язковою:
interface UserProfile {
name: string;
age?: number;
}Тепер можна створити об’єкт як із властивістю age, так і без неї:
const firstProfile: UserProfile = {
name: "Марія",
};
const secondProfile: UserProfile = {
name: "Андрій",
age: 28,
};Оскільки властивість може бути відсутньою, під час роботи з нею потрібно враховувати значення undefined:
function printAge(profile: UserProfile): void {
if (profile.age !== undefined) {
console.log(`Вік: ${profile.age}`);
} else {
console.log("Вік не вказано");
}
}Модифікатор readonly забороняє змінювати властивість після створення об’єкта:
interface Account {
readonly id: number;
owner: string;
}
const account: Account = {
id: 101,
owner: "Олег",
};
account.owner = "Олексій";
// Помилка: властивість id доступна лише для читання
// account.id = 102;readonly захищає властивість на рівні перевірки TypeScript. Він не робить об’єкт повністю незмінним під час виконання JavaScript.
Інтерфейс може описувати не лише властивості, а й методи об’єкта.
Для цього вказують назву методу, його параметри та тип значення, яке він повертає:
interface Calculator {
add(first: number, second: number): number;
subtract(first: number, second: number): number;
}Об’єкт, який відповідає цьому інтерфейсу, повинен реалізувати обидва методи:
const calculator: Calculator = {
add(first, second) {
return first + second;
},
subtract(first, second) {
return first - second;
},
};
console.log(calculator.add(10, 5)); // 15
console.log(calculator.subtract(10, 5)); // 5Параметри методів у цьому прикладі автоматично отримують типи з інтерфейсу:
first має тип number;
second має тип number;
результат кожного методу має тип number.
Метод також можна описати як властивість-функцію:
interface Logger {
log: (message: string) => void;
}
const logger: Logger = {
log(message) {
console.log(message);
},
};Обидва синтаксиси описують функціональну поведінку об’єкта. Для методів об’єкта частіше використовують короткий синтаксис:
interface Greeter {
greet(name: string): string;
}У наступному прикладі інтерфейс описує товар із властивостями та методом:
interface Product {
readonly id: number;
name: string;
price: number;
description?: string;
getInfo(): string;
}
const product: Product = {
id: 1,
name: "Навушники",
price: 1800,
description: "Бездротові навушники",
getInfo() {
const description = this.description ?? "Опис відсутній";
return `${this.name}: ${this.price} грн. ${description}`;
},
};
console.log(product.getInfo());
// Властивість name можна змінювати
product.name = "Бездротові навушники";
// Властивість id має readonly і не повинна змінюватися
// product.id = 2;Тут:
id — обов’язкова властивість лише для читання;
name і price — обов’язкові властивості;
description — необов’язкова властивість;
getInfo — обов’язковий метод;
this усередині методу посилається на поточний об’єкт.
Інтерфейси зручно використовувати для типізації параметрів функцій:
interface Order {
id: number;
customer: string;
total: number;
}
function printOrder(order: Order): void {
console.log(`Замовлення №${order.id}`);
console.log(`Клієнт: ${order.customer}`);
console.log(`Сума: ${order.total} грн`);
}
const order: Order = {
id: 5001,
customer: "Наталія",
total: 3200,
};
printOrder(order);Функція printOrder приймає лише об’єкти, які відповідають інтерфейсу Order.
Це допомагає:
бачити структуру даних прямо в коді;
отримувати підказки від редактора;
виявляти помилки ще до запуску програми;
повторно використовувати один опис у різних функціях.
Інтерфейс також можна використовувати для опису значення, яке повертає функція:
interface Coordinates {
latitude: number;
longitude: number;
}
function getCoordinates(): Coordinates {
return {
latitude: 50.4501,
longitude: 30.5234,
};
}
const coordinates = getCoordinates();
console.log(coordinates.latitude);
console.log(coordinates.longitude);Тепер TypeScript знає, що результат getCoordinates() має властивості latitude та longitude.
Один інтерфейс може розширювати інший за допомогою extends. Новий інтерфейс успадковує всі властивості батьківського інтерфейсу.
interface Person {
name: string;
age: number;
}
interface Employee extends Person {
position: string;
}
const employee: Employee = {
name: "Софія",
age: 30,
position: "Frontend Developer",
};Employee містить:
name та age з інтерфейсу Person;
власну властивість position.
Розширення допомагає не дублювати однакові властивості в кількох інтерфейсах.
interface Contact {
email: string;
}
interface Customer extends Person, Contact {
customerId: number;
}
const customer: Customer = {
name: "Тарас",
age: 35,
email: "taras@example.com",
customerId: 42,
};Інтерфейс може розширювати кілька інших інтерфейсів.
TypeScript перевіряє, чи не містить об’єкт зайвих властивостей, коли об’єкт передається безпосередньо там, де очікується інтерфейс:
interface Point {
x: number;
y: number;
}
const point: Point = {
x: 10,
y: 20,
// Помилка: властивість color не описана в Point
// color: "red",
};Якщо об’єкт спочатку зберегти в змінній, TypeScript може дозволити додаткові властивості, але під час використання за типом Point доступними будуть лише x і y:
const data = {
x: 10,
y: 20,
color: "red",
};
const point: Point = data;
console.log(point.x);
console.log(point.y);
// Помилка: властивість color відсутня в типі Point
// console.log(point.color);Якщо додаткова властивість справді потрібна, її слід додати до інтерфейсу.
Інтерфейс можна використовувати для масиву об’єктів:
interface Task {
id: number;
title: string;
completed: boolean;
}
const tasks: Task[] = [
{
id: 1,
title: "Вивчити інтерфейси",
completed: true,
},
{
id: 2,
title: "Написати практичний приклад",
completed: false,
},
];
function printCompletedTasks(taskList: Task[]): void {
for (const task of taskList) {
if (task.completed) {
console.log(task.title);
}
}
}
printCompletedTasks(tasks);Запис Task[] означає масив елементів типу Task.
interface і typeДля опису об’єктів можна використовувати і interface, і type:
interface User {
name: string;
age: number;
}
type Product = {
name: string;
price: number;
};На початковому етапі зручно запам’ятати таке правило:
interface часто використовують для форми об’єктів і класів;
type також описує об’єкти, але додатково зручно працює з об’єднаннями та іншими складеними типами.
У цій темі для опису об’єктів використовуємо interface.
interface Book {
title: string;
pages: number;
}
const book: Book = {
title: "TypeScript для початківців",
// Помилка: відсутня властивість pages
};Потрібно додати всі властивості, які не позначені як необов’язкові.
interface Settings {
theme: string;
fontSize: number;
}
const settings: Settings = {
theme: "dark",
fontSize: "large",
// Помилка: fontSize має бути number
};Значення властивості повинно відповідати типу в інтерфейсі.
interface Formatter {
format(value: number): string;
}
const formatter: Formatter = {
format(value) {
return value;
},
// Помилка: метод повинен повертати string
};Сигнатура методу в об’єкті повинна відповідати сигнатурі в інтерфейсі.
interface Profile {
name: string;
nickname?: string;
}
function printNickname(profile: Profile): void {
if (profile.nickname) {
console.log(profile.nickname.toUpperCase());
}
}Необов’язкова властивість може бути undefined, тому перед використанням її потрібно перевірити.
interface описує форму об’єкта.
Властивість інтерфейсу має назву та тип.
За замовчуванням усі властивості є обов’язковими.
Знак ? робить властивість необов’язковою.
readonly забороняє змінювати властивість через тип TypeScript.
Інтерфейси можуть описувати методи об’єктів.
Інтерфейси можна використовувати для параметрів і результатів функцій.
extends дає змогу створювати нові інтерфейси на основі наявних.
Один інтерфейс можна застосовувати для типізації окремих об’єктів, масивів об’єктів і даних у функціях.