TypeScript Declaration Merging

Apr 06, 2023#typescript

TypeScript declaration merging allows multiple declarations of the same name to be merged into a single definition. This can be done for interfaces, namespaces, enums and other types. Currently, classes can not merge with other classes or with variables.

interface Person {
  name: string;
}

interface Person {
  age: number;
}

let person: Person = {
  name: "John",
  age: 30,
};

Some basic rules for declaration merging are:

  • Non-function members of the interfaces should be unique. If they are not unique, they must be of the same type.
  • For function members, each function member of the same name is treated as describing an overload of the same function.
  • The order of the merged declarations matters. The later declarations have higher precedence than the earlier ones.
  • One exception to this rule is specialized signatures. If a signature has a parameter whose type is a single string literal type (e.g. not a union of string literals), then it will be bubbled toward the top of its merged overload list.

This is useful when working with third-party libraries or other code that does not provide TypeScript types.

Here’s an example of what the styled.d.ts declaration file might look like to create custom theme for styled-components:

// import original module declarations
import 'styled-components';

// and extend them!
declare module 'styled-components' {
  export interface DefaultTheme {
    borderRadius: string;

    colors: {
      main: string;
      secondary: string;
    };
  }
}