interface: объявление и использование

interface в TypeScript — декларация структурного контракта для объекта: описывает набор обязательных и опциональных свойств и методов, которым должно соответствовать значение.

Зачем нужно

Interface — основной способ описать форму объекта в TypeScript. Он создаёт именованный тип, который можно переиспользовать, расширять через extends и дополнять через declaration merging. В отличие от type alias, interface ориентирован именно на объектные контракты.

Где используется

  • Описание моделей данных: User, Product, Order
  • Контракты API-ответов и DTO
  • Параметры функций и возвращаемые значения
  • Контракты для классов через implements
  • Конфигурационные объекты

Основной контент

Базовое объявление

interface User {
  id: string;
  name: string;
  email: string;
  age?: number;         // опциональное
  readonly createdAt: Date; // только чтение
}

const alice: User = {
  id: "u-1",
  name: "Alice",
  email: "alice@example.com",
  createdAt: new Date,
};

Методы в интерфейсе

interface Calculator {
  add(a: number, b: number): number;
  subtract(a: number, b: number): number;
  multiply(a: number, b: number): number;
  // Метод как свойство-функция:
  divide: (a: number, b: number) => number;
}

const calc: Calculator = {
  add: (a, b) => a + b,
  subtract: (a, b) => a - b,
  multiply: (a, b) => a * b,
  divide: (a, b) => a / b,
};

Index Signatures — динамические ключи

interface StringMap {
  [key: string]: string;
}

interface NumberDictionary {
  [index: number]: string;
  length: number;       // OK — совместим с string
}

const translations: StringMap = {
  hello: "привет",
  goodbye: "пока",
};

Callable и Constructable

// Callable interface — объект можно вызвать как функцию
interface Formatter {
  (value: string): string;
  locale: string;   // дополнительные свойства
}

// Constructable — объект можно вызвать через new
interface ClockConstructor {
  new (hour: number, minute: number): ClockInterface;
}

interface ClockInterface {
  tick: void;
}

Declaration Merging — расширение из разных мест

interface Window {
  customProp: string; // добавляется к встроенному Window
}

// Также в двух файлах:
interface Config { host: string; }
interface Config { port: number; }
// Итог: { host: string; port: number }

Расширение через extends

interface Animal {
  name: string;
}

interface Dog extends Animal {
  breed: string;
}

interface PoliceDog extends Dog {
  badgeNumber: string;
}

const k9: PoliceDog = {
  name: "Rex",
  breed: "Shepherd",
  badgeNumber: "K9-007",
};

Частые ошибки

  • Ожидать declaration merging для type alias — merging работает только с interface; два type User = ... вызовут ошибку дублирования.
  • Не различать method: void и method: => void — разница в ковариантности при strictFunctionTypes; для методов TypeScript мягче.
  • Index signature несовместим с конкретными типами[key: string]: string требует что ВСЕ поля, включая конкретные, имели тип string.
  • Использовать interface для unioninterface A = B | C не работает; для union нужен type.

Связанные темы

Ресурсы