TypeScript Tips Part II: Declaration Merging

Nick Taylor - Feb 12 '19 - - Dev Community

Declaration merging has been around for a while now in TypeScript. In a nutshell it lets you merge definitions of types.
There's plenty of examples in the documentation, so let's just start off with something simple.

enum HardDriveType {
    ssd,
    sata
}

enum ProcessorType {
    i3,
    i5,
    i7,
    i9
}

interface Computer {
    processor: ProcessorType;
}

interface Computer {
    hardDriveType: HardDriveType;
}

// interface has been merged
const myPC: Computer = {
    hardDriveType: HardDriveType.ssd,
    processor: ProcessorType.i9
};

// interface is merged so type checking fails since the processor property is missing
const myBadPC: Computer = {
    hardDriveType: HardDriveType.ssd,
};
Enter fullscreen mode Exit fullscreen mode

You can play around with the example in the TypeScript Playground.
So two interfaces called Computer are declared and all the properties of those interfaces are merged together into one declaration for the Computer interface. This is a simple example to show how it works, but in a real world app, you wouldn't be declaring the interface in two pieces in a file. Let's go with something more realistic.

You are using a third-party library or it's something in your project that needs to live on the window. The window has it's own type, the Window interface. This type has all the properties you'd expect to find on MDN about window.

Let's use our a fictitious 3rd party library called awesomeThing. It gets loaded onto the window object so we need to enhance the Window interface.

export interface AwesomeThing {
    doIt: () => void;
}

declare global {
    interface Window {
        awesomeThing: AwesomeThing
    }
}

// The window interface has been merged with our interface to add awesomeThing.
window.awesomeThing.doIt();

// Errors because it's not on the `Window` interface.
window.thingThatIsNotOnWindow.doIt();
Enter fullscreen mode Exit fullscreen mode

You can play around with the example in the TypeScript Playground.

If you'd like to see some real world examples in open source, look no further than a recent PR of mine that got merged to the Refined GitHub browser extension repository. I was really happy getting this PR in because it's an extension I use everyday.

Specifically, check out globals.d.ts in the project.

That's pretty much all there is to it. To summarize, declaration merging is a great way to enhance existing types.

Photo by Mike Enerio on Unsplash

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .