Skip to main content

Однакове ім'я інтерфейсів

1. Якщо два інтерфейси мають однакове ім'я...

...TypeScript не видасть помилку, а об'єднає їх (складе всі поля разом).

Ця поведінка називається declaration merging - "злиття оголошень".


Приклад

javascript
interface User { id: number; } interface User { name: string; } const u: User = { id: 1, name: "Tim", };

Результат: TypeScript об'єднав обидва інтерфейси в один:

javascript
// Компілятор бачить це так: interface User { id: number; name: string; }

2. Як працює об'єднання

Коли TypeScript бачить кілька інтерфейсів з однаковим ім'ям:

  1. Він не замінює старе оголошення новим.
  2. Він об'єднує їх - додаючи поля, методи і типи з обох.
  3. Якщо та сама властивість зустрічається в обох - TypeScript перевіряє, чи сумісні типи цих властивостей.

Приклад з однаковими типами полів

javascript
interface Product { id: number; } interface Product { title: string; } const p: Product = { id: 10, title: "Shirt" }; // OK

Об'єднання успішне - поля різні.


Приклад з конфліктуючими типами

javascript
interface Product { id: number; } interface Product { id: string; } // Помилка: типи несумісні const p: Product = { id: "10" };

TypeScript не може об'єднати number і string для однієї і тієї ж властивості.


3. Можна об'єднувати не тільки поля, а й методи

javascript
interface Logger { log(msg: string): void; } interface Logger { warn(msg: string): void; } const logger: Logger = { log: (msg) => console.log(msg), warn: (msg) => console.warn(msg), };

TypeScript створить об'єднаний інтерфейс з обома методами.


4. Порядок об'єднання має значення (в особливих випадках)

Якщо методи мають однакові імена, але різні сигнатури - TypeScript об'єднує їх як перевантаження, і порядок оголошення впливає на пріоритет.

javascript
interface Example { doThing(a: number): void; } interface Example { doThing(a: string): void; } const e: Example = { doThing(a) { console.log(a); }, };

Тут інтерфейс Example має дві сигнатури методу - doThing(a: string) і doThing(a: number).


5. Де це використовується на практиці

Розширення типів із бібліотек

Наприклад, можна додати власні поля в інтерфейс Express.Request:

javascript
// у твоєму проєкті declare module "express" { interface Request { user?: { id: number; name: string }; } }

TypeScript об'єднає твоє оголошення з оригінальним інтерфейсом Express. Тепер req.user буде типізований!


Розширення глобальних типів

javascript
interface Window { myAppVersion?: string; } window.myAppVersion = "1.2.3";

Тепер властивість window.myAppVersion коректно типізована, хоча її не було в стандартному інтерфейсі.


6. На відміну від type

type не підтримує об'єднання:

javascript
type User = { id: number }; type User = { name: string }; // Помилка: повторне визначення типу

У type - строгі межі: одне ім'я = одне оголошення.

А інтерфейси, навпаки, можуть об'єднуватися - саме тому їх часто використовують для розширення наявних API.


Підсумок

Якщо в TypeScript оголосити два інтерфейси з однаковим ім'ям, вони об'єднаються в один.

Це називається declaration merging.

Правила:

  • усі поля об'єднуються в один інтерфейс;
  • якщо та сама властивість повторюється - типи повинні бути сумісними;
  • методи з однаковими іменами об'єднуються як перевантаження;
  • працює лише з interface, не з type.

Це використовується для:

  • розширення бібліотек (Express, React, Node API);
  • додавання кастомних властивостей глобальним типам (Window, Document тощо).

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.