Что такое интерфейсы в TypeScript и для чего они применяются?

В TypeScript интерфейсы — это один из ключевых инструментов статической типизации. Они позволяют описывать структуру объектов, определять контракты для классов и задавать правила взаимодействия различных частей программы. Интерфейсы делают код более предсказуемым, удобным для поддержки и помогают сократить количество ошибок на этапе компиляции.

Что такое интерфейс

Интерфейс в TypeScript — это способ определить форму объекта. Он описывает, какие свойства и методы объект должен содержать, а также их типы. Интерфейс не создает конкретной реализации, а служит контрактом, который нужно выполнить.

Пример простого интерфейса:

interface User {
id: number;
name: string;
isActive: boolean;
}

Здесь интерфейс User определяет, что объект должен содержать три свойства: id, name и isActive с соответствующими типами.

Использование интерфейсов для объектов

Интерфейсы позволяют описывать типы объектов и использовать их при объявлении переменных, аргументов функций или возвращаемых значений.

function printUser(user: User): void {
console.log(\`${user.name} (${user.id}) - Active: ${user.isActive}\`);
}

Если разработчик передаст в функцию объект, который не соответствует интерфейсу User, компилятор выдаст ошибку.

Интерфейсы и необязательные свойства

Иногда не все поля объекта обязательны. Для таких случаев интерфейсы поддерживают модификатор ?.

interface Product {
id: number;
title: string;
description?: string;
}

Свойство description здесь является необязательным, и объект будет корректен как с ним, так и без него.

Интерфейсы и readonly

Интерфейсы позволяют помечать свойства как только для чтения. Это помогает защитить объект от изменения определённых полей.

interface Config {
readonly apiKey: string;
timeout: number;
}

Свойство apiKey нельзя будет изменить после инициализации объекта.

Интерфейсы и функции

Интерфейс может описывать не только объект, но и сигнатуру функции.

interface Logger {
(message: string, level: number): void;
}

Здесь интерфейс задает форму функции, которая принимает два параметра и ничего не возвращает.

Интерфейсы и классы

Интерфейсы активно применяются для описания контрактов, которые должны реализовать классы.

interface Shape {
getArea(): number;
}
class Circle implements Shape {
constructor(private radius: number) {}
getArea(): number {
return Math.PI \* this.radius \*\* 2;
}
}

Класс Circle обязан реализовать метод getArea, потому что он определён в интерфейсе Shape.

Расширение интерфейсов

Интерфейсы могут наследоваться друг от друга с помощью ключевого слова extends. Это позволяет создавать более сложные структуры без дублирования кода.

interface Person {
name: string;
}
interface Employee extends Person {
employeeId: number;
}

Интерфейс Employee наследует свойства интерфейса Person и добавляет собственное поле.

Гибкость интерфейсов

Интерфейсы позволяют создавать индексные сигнатуры, если структура объекта заранее неизвестна.

interface Dictionary {
\[key: string\]: string;
}

В этом случае объект может содержать произвольное количество строковых ключей с типом значения string.