← Назад к вопросам

Что будет, если создать два интерфейса с одинаковым именем в одном файле?

2.0 Middle🔥 171 комментариев
#JavaScript Core

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Поведение интерфейсов с одинаковыми именем в TypeScript

В TypeScript создание двух интерфейсов с одинаковым именем в одном файле не вызывает ошибки компиляции — вместо этого происходит слияние (merge) их определений. Этот механизм называется Declaration Merging и является одной из ключевых особенностей TypeScript, позволяющей расширять типы постепенно.

Механизм слияния интерфейсов

Когда объявляются два интерфейса с одним именем, TypeScript автоматически объединяет их свойства в единый тип. Это полезно, например, при расширении библиотечных интерфейсов или декомпозиции сложных типов на части.

// Первый интерфейс
interface User {
  name: string;
  age: number;
}

// Второй интерфейс с тем же именем
interface User {
  email: string;
  role: "admin" | "user";
}

// Результирующий тип после слияния
const user: User = {
  name: "Alice",
  age: 28,
  email: "alice@example.com",
  role: "admin", // все свойства обязательны
};

Правила слияния

  1. Объединение свойств: Если свойства имеют разные имена, они просто добавляются в итоговый интерфейс.
  2. Конфликты типов: Если одно свойство объявлено в обоих интерфейсах, их типы должны быть совместимы (одинаковы или один является подтипом другого). Несовпадение приведет к ошибке:
interface A { x: string; }
interface A { x: number; } // Ошибка: свойство 'x' конфликтует
  1. Методы и функции: Для методов допускается перегрузка (overloading) — несколько объявлений одной функции с разными параметрами:
interface Handler {
  process(data: string): void;
}
interface Handler {
  process(data: number): void;
}
// Результат: process(data: string | number): void

Практическое применение

Слияние интерфейсов часто используется в:

  • Расширении стандартных типов (например, добавление полей к Window в веб-приложениях).
  • Разделении деклараций при работе с большими конфигурационными объектами.
  • Интеграции с библиотеками, где основные интерфейсы дополняются модульно.
// Пример расширения интерфейса Window
interface Window {
  myGlobalVar: string;
}
interface Window {
  customMethod(): void;
}
// Теперь window.myGlobalVar и window.customMethod доступны

Ограничения и альтернативы

Механизм работает только для интерфейсов, но не для типов (type), объявленных через type. Попытка создать два одноимённых type вызовет ошибку:

type Person = { name: string };
type Person = { age: number }; // Ошибка: дублирование идентификатора

Для сложных расширений, где требуется явный контроль, лучше использовать:

  • Расширение через наследование: interface ExtendedUser extends BaseUser { ... }
  • Комбинацию типов: type Combined = A & B (объединение через пересечение)
  • Декомпозицию на разные именованные интерфейсы.

Выводы

Слияние интерфейсов в TypeScript — это мощный инструмент для инкрементного определения типов, но он требует осторожности при наличии потенциальных конфликтов. Его использование оправдано при работе с внешними API или поэтапном описании сложных структур данных, однако в собственной кодовой базе чаще предпочтительны более явные методы расширения типов для сохранения читаемости и избежания неожиданных конфликтов.