ProgrammingFullstack Developer

What is Declaration Merging in TypeScript and how does it work in practice?

Pass interviews with Hintsage AI assistant

Answer.

Background

Declaration Merging is a unique feature of TypeScript that allows combining multiple declarations with the same name into a single entity. This is tied to the history of TypeScript as a type system over JavaScript: many third-party libraries declare interfaces, functions, namespaces, and TypeScript needed to allow them to be extended without modifying the library's source code.

Problem

In complex APIs and when typing third-party JS libraries, it may be necessary to separate responsibilities — for example, to extend module types, add fields to interfaces, or merge names. However, most languages do not support such declaration merging.

Solution

TypeScript allows merging (merging) interface declarations, namespaces, functions, and classes with the same names, making the API flexible for extension. It is used to extend third-party types, add custom methods to libraries, and organize modular code.

Code example:

// 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!"

Key features:

  • Allows merging interfaces, functions with namespace, enums with namespace, but not types.
  • Used for describing extensible APIs and global declaration extensions.
  • Allows safe modification/extending of types from third-party libraries without changing them.

Trick Questions.

Can type aliases be merged like interfaces?

No, type aliases cannot be merged. Attempting to declare multiple types with the same name will result in a compilation error.

type T = { a: string }; type T = { b: number }; // Error

Will TypeScript insert fields of an interface/namespace in a random order?

The merged structure is always built in declaration order — if there are properties with the same names, the last declaration "wins".

Are methods of an interface merged into a single function?

No, methods with the same names in different interfaces are not merged into a single function — if the signatures match, TypeScript will still not allow implementing "both" variants.

Common Errors and Anti-patterns

  • Attempting to merge type aliases or enums without namespaces will cause an error.
  • Duplicate fields with different types inside interfaces create a conflict and cannot be merged;
  • Using merging without a conscious need leads to unreadable code.

Real-life Example

Negative Case

A company defines the global interface Window twice with different fields and different types for a field with the same name. During the build, the compiler does not notice the problem, but at runtime, an unexpected type conflict occurs.

Pros:

  • Quick way to "extend" an interface without changing the source.

Cons:

  • Conflicting names lead to bugs, which are hard to find.
  • Often makes understanding the complete structure of the type difficult.

Positive Case

A d.ts file is written for a third-party library, where the API interface is extended by separate modules without changing the library itself, all extensions are documented, and the naming policy is described in the Wiki.

Pros:

  • Safe extension of a third-party API.
  • Improvements and additions can be gradually implemented.

Cons:

  • Documentation for correspondences and naming must be maintained.
  • The risk of conflicts increases in larger teams without strict naming policy.