DEV Community

Cover image for What is Declaration merging in Typescript?
Shakvilla
Shakvilla

Posted on • Updated on • Originally published at Medium

 

What is Declaration merging in Typescript?

What is Declaration merging in typescript?

  • Explanation:

    In typescript, a value, a type and a namespace can be stacked on each other as a
    single entity and exported out with a single identifier.

💡Namespace-creating declarations create a namespace, which contains names
that are accessed using a dotted notation. Type-creating declarations do just that:
they create a type that is visible with the declared shape and bound to the given
name. Lastly, value-creating declarations create values that are visible in the output
JavaScrip

Declaration Type Namespace Type Value
Namespace X X
type alias X
interface X
class X X
enum X X
function X
variable X
  • Merging Interfaces

    Interfaces are the most common declaration merging type in typescript, members of the declared interface types are simply merged into a single interface and assigned a single identifier.

    interface User{
        id: number;
        name: string;
        job: string;
        salary: string;
    }
    
    interface User {
        gender: string;
        isMarried: boolean;
    
    }
    
    const user: User = {
    id: 3, 
    name: "Abdul Shakur", 
    job: "software developer",                          
    salary: $4000, 
    gender: "male", 
    isMarried: true 
    }   
    

    Note: The last interface always has the highest precedence when merging.

    For function members, each function member of the same name is treated as
    describing an overload of the same function. Of note, too, is that in the case of
    interface A merging with later interface A, the second interface will have higher
    precedence than the first.

    interface Document {
      createElement(tagName: any): Element;
    }
    interface Document {
      createElement(tagName: "div"): HTMLDivElement;
      createElement(tagName: "span"): HTMLSpanElement;
    }
    interface Document {
      createElement(tagName: string): HTMLElement;
      createElement(tagName: "canvas"): HTMLCanvasElement;
    }   
    

    The resulting merged declaration of Document will be as follows

    interface Document {
      createElement(tagName: "canvas"): HTMLCanvasElement;
      createElement(tagName: "div"): HTMLDivElement;
      createElement(tagName: "span"): HTMLSpanElement;
      createElement(tagName: string): HTMLElement;
      createElement(tagName: any): Element;
    }
    
  • Merging Namespaces

    Namespace with the same name will merge their members and export as single entity. We need to understand that namespaces create a namespace and a value.

    To merge the namespaces, the type definitions exported interfaces declared in each namespace are themselves merged, to form a single namespace with merged type definitions in it.

    To merge the namespace value, once a namespace with the same name already exist, typescript will maintain the existing namespace and only extend it by adding the members of the subsequent namespaces, with the same name, to the first namespace.

    Code Example:

    namespace UsersDB{
      export class AdminUser {}
    }
    
    namespace UsersDB {
    
    // un-exported type declaration
    interface Staff {
      staffID: number;
      name: string;
      role: string[];
      salary?: string;
      department: string;
    
    }
    
    // exported type declaratio
     export interface User {
      id: number;
      name: string;
      job: string;
      salary: string;
     }
    
    // exported type declaration
     export class ClientUser{}
    
    }
    

    This model of namespace merging is a helpful starting place, but we also need to understand what happens with non-exported members. Non-exported members are only visible in the original (un-merged) namespace. This means that after merging, merged members that came from other declarations cannot see non-exported members.

    When the code snippets above are merged, the code below will be the result;

    namespace UsersDB {
      export interface User {
        id: number;
        name: string;
        job: string;
        salary: string;
      }
      export class AdminUser {}
      export class ClientUser {}
    
    }
    
  • Merging Namespaces with classes

    The TS Compiler will merge members of a class and a namespace if they both have the same name. The members have to be exported in other to be recognised in the merged type declaration.

    class ClientsDB {
      client!: ClientsDB.ClientName;
    }
    
    namespace ClientsDB {
      export class ClientName{
    
      }
    }
    
  • Merging Namespaces with function

    We could define a function and a namespace that “stack” like this, so that $
     could simultaneously be invoked directly, and serve as a namespace for things like 
    $.ajax$.getJSON and so on…

    function $(selector: string): NodeListOf<Element> {
      return document.querySelectorAll(selector)
    }
    namespace $ {
      export function ajax(arg: {
        url: string
        data: any
        success: (response: any) => void
      }): Promise<any> {
        return Promise.resolve()
      }
    }
    

Top comments (0)

The JavaScript Brief

1. Top 5 MERN STACK projects to improve your practical understanding

Boost your MERN Stack development skills by undertaking interesting beginner projects. These five engaging projects cover web applications and range from social media website applications to geo-social networking maps. Hone your understanding and apply modern techniques backed up by hands-on experience.

2. How To Optimize Your React App’s Performance

Learn the best optimizing techniques to make your React applications faster and more efficient. Focusing on the identification of performance bottlenecks and common pitfalls to avoid, these optimization strategies will keep your applications running smoothly even when faced with growing complexity.

3. A story of let, const, object mutation, and a bug in my code

In the pursuit of bug-free code, explore an incident involving a mix-up between const and let, making sure your custom code works effectively with third

party documentation. Discover best practices on program flow and learn about JavaScript's unpredictable aspects to ensure your core code is robust.