Skip to main content

Extending Interfaces

A core superpower of Interfaces over Type Aliases is their ability to neatly extend configurations via the extends keyword, allowing modular, reusable object shapes without copy-pasting code!

The extends Keyword

interface Animal {
name: string;
age: number;
}

// Dog INHERITS 'name' and 'age' from 'Animal'
interface Dog extends Animal {
breed: string;
}

const myPet: Dog = {
name: "Buddy",
age: 3,
breed: "Golden Retriever"
};

Multiple Inheritance

Unlike native Java or C# classes, a TypeScript interface can actually string together inheritances from multiple different interfaces!

interface Flyable {
wingSpan: number;
}

interface Swimmable {
diveDepth: number;
}

// Combining both shapes into a super Duck!
interface Duck extends Flyable, Swimmable {
beakColor: string;
}

const donald: Duck = {
wingSpan: 24,
diveDepth: 10,
beakColor: "Yellow"
};

Interface Declaration Merging

Interfaces possess a unique behavior called Declaration Merging. If you declare an interface twice targeting the exact same name, TypeScript will NOT throw an error causing collisions. Instead, it natively merges the properties sequentially into a single super-interface! Type Aliases completely flat-out crash if you attempt this.

interface Window {
title: string;
}

// Further down the file, or pulling from a 3rd party package:
interface Window {
width: number;
height: number;
}

// TS compiles and merges them perfectly
const appWindow: Window = {
title: "App",
width: 1920,
height: 1080
};