Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Однакове ім'я інтерфейсів». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)Якщо два **інтерфейси** мають однакове ім'я, TypeScript не видає помилку, а об'єднує їх, складаючи всі поля разом - це поведінка називається **declaration merging**. **Ключове:** об'єднання працює лише з `interface`, а не з `type`; якщо однакова властивість повторюється в обох оголошеннях, її типи повинні бути сумісними, інакше TypeScript видасть помилку.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## 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` тощо).Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.