Skip to main content

Same interface name

1. If two interfaces have the same name...

...TypeScript does not throw an error, it merges them (combines all the fields together).

This behavior is called declaration merging.


Example

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

Result: TypeScript merged both interfaces into one:

javascript
// The compiler sees it as this: interface User { id: number; name: string; }

2. How the merge works

When TypeScript sees several interfaces with the same name:

  1. It does not replace the old declaration with the new one.
  2. It merges them, adding fields, methods, and types from both.
  3. If the same property appears in both, TypeScript checks whether the types of that property are compatible.

An example with matching field types

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

The merge succeeds - the fields are different.


An example with conflicting types

javascript
interface Product { id: number; } interface Product { id: string; } // Error: incompatible types const p: Product = { id: "10" };

TypeScript cannot merge number and string for the same property.


3. Not just fields can be merged, methods too

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 creates a merged interface with both methods.


4. Merge order matters (in special cases)

If methods have the same names but different signatures, TypeScript merges them as overloads, and the declaration order affects priority.

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

Here the Example interface has two method signatures - doThing(a: string) and doThing(a: number).


5. Where this is used in practice

Extending types from libraries

For example, you can add your own fields to the Express.Request interface:

javascript
// in your project declare module "express" { interface Request { user?: { id: number; name: string }; } }

TypeScript merges your declaration with Express's original interface. Now req.user will be typed!


Extending global types

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

Now the window.myAppVersion property is correctly typed, even though it was not in the standard interface.


6. Unlike type

type does not support merging:

javascript
type User = { id: number }; type User = { name: string }; // Error: duplicate type definition

type has strict boundaries: one name equals one declaration.

Interfaces, on the other hand, can be merged - that is exactly why they are often used to extend existing APIs.


Summary

If you declare two interfaces with the same name in TypeScript, they will merge into one.

This is called declaration merging.

The rules:

  • all fields are merged into one interface;
  • if the same property repeats, the types must be compatible;
  • methods with the same names are merged as overloads;
  • it only works with interface, not with type.

This is used for:

  • extending libraries (Express, React, Node API);
  • adding custom properties to global types (Window, Document, etc.).

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.