Declaration Merging — уникальная особенность TypeScript, которая позволяет объединять несколько деклараций с одинаковыми именами в одну сущность. Это связано с историей TypeScript как типизации над JavaScript: многие сторонние библиотеки объявляли интерфейсы, функции, пространства имён, и TypeScript должен был позволять их расширять без модификации исходного кода библиотеки.
В сложных API и при типизации сторонних JS-библиотек может потребоваться разделить ответственность — например, расширить типы модуля, добавить поля интерфейса, объединить имена. Однако большинство языков не поддерживают подобное объединение деклараций.
TypeScript позволяет сливать (merge) объявления интерфейсов, пространств имён (namespace), функций, классов с одинаковыми именами, что делает API гибким для расширения. Используется для расширения сторонних типов, добавления кастомных методов библиотекам, а также организации модульного кода.
Пример кода:
// interfaces merging interface User { id: number; } interface User { name: string; } const u: User = { id: 1, name: "Jack" }; // namespace + function merging function greet() { return "Hi!"; } namespace greet { export function loud() { return "HI!"; } } greet(); // "Hi!" greet.loud(); // "HI!"
Ключевые особенности:
Можно ли объединять type alias аналогично интерфейсам?
Нет, type alias невозможно объединять. При попытке объявить несколько type с одним именем будет ошибка компиляции.
type T = { a: string }; type T = { b: number }; // Ошибка
Вставит ли TypeScript поля интерфейса/пространства имён в случайном порядке?
Слитая структура всегда строится в порядке объявления — если есть одинаковые имена свойств, последняя декларация "побеждает".
Объединяются ли методы интерфейса в одну функцию?
Нет, методы с одинаковыми названиями в разных интерфейсах не сливаются в одну функцию — если сигнатуры совпадают, TypeScript всё равно не позволит реализовать "оба" варианта.
Компания определяет глобальный интерфейс Window дважды с разными полями и разными типами для поля с одинаковым именем. Во время сборки сборщик не замечает проблему, а при запуске появляется неожиданный конфликт типов.
Плюсы:
Минусы:
Пишется d.ts-файл к сторонней библиотеке, где интерфейс API расширяется отдельными модулями без изменения самой библиотеки, все расширения документированы, naming policy описана в Wiki.
Плюсы:
Минусы: