How to Define Interfaces in TypeScript

Updated: January 7, 2024 By: Guest Contributor Post a comment

Overview

When the pageantry of programming translates to the TypeScript stage, interfaces become the pivotal characters that ensure the harmony of types. They are akin to the contracts in which, with ironclad words, one foretells the shape of things yet made.

Introduction

TypeScript, the scribe of JavaScript, weaves in type safety with a gentle hand, turning the loose threads of dynamic types into a well-knitted type system. Interfaces in TypeScript are the blueprint from which objects gain their form, ensuring each property and function meets a predetermined standard. As one would follow a river to reach the ocean, this article shall lead you step by step, from the headwaters of interfaces to the advanced deltas that might yet require a seasoned type-crafter’s acumen.

Defining Simplicity: Basic Interfaces

interface Greeter {
    greet(): string;
}

function welcomeSomeone(greeter: Greeter) {
    return greeter.greet();
}

const cheerfulGreeter = {
    greet() {
        return "Hello, fine folk!";
    }
};

console.log(welcomeSomeone(cheerfulGreeter)); // 'Hello, fine folk!'

In the vein of Mississippian tributaries, basic interfaces do start simply, defying their power to hold Spartan stipulations that shape objects with ease.

Growing Complexity: Properties & Methods

interface Author {
    name: string;
    write(): string;
}

const markTwain: Author = {
    name: 'Mark Twain',
    write() {
        return "The finest of tales from the heart of the Mississippi!";
    }
};

console.log(markTwain.write()); // 'The finest of tales from the heart of the Mississippi!'

The fertile soil of our interfaces grows richer with properties and methods that gestate fully formed objects as if by some literary agriculture.

Optional Properties and Readonly Contracts

interface Novel {
    readonly title: string;
    readonly author: string;
    genre?: string;
}

const huckleberryFinn: Novel = {
    title: 'Adventures of Huckleberry Finn',
    author: 'Mark Twain',
    // genre is optional
};

// huckleberryFinn.title = 'Another Title'; // Error: Cannot assign to 'title' because it's readonly.

Just as our wilderness flourishes with the array of creatures in the shadows and light, optional properties allow an interface to entertain the ambiguity, while readonly erects immutable signposts upon the journey.

Function Types and Indexable Types

interface StringDictionary {
    [index: string]: string;
}

interface ReturnString {
    (word: string): string;
}

const dict: StringDictionary = {
    quixotic: 'exceedingly idealistic',
    soliloquy: 'an act of speaking one's thoughts aloud'
};

const repeat: ReturnString = (word) => `${word} ${word}`;

console.log(dict['quixotic']); // 'exceedingly idealistic'
console.log(repeat('Mark Twain')); // 'Mark Twain Mark Twain'

Our pen now draws function types and indexables, casting a spell where one may index into the heartstrings of a dictionary, or summon words with incantations that charm duplicates from the aether.

Interface Extending Interface

interface LiteraryWork {
    title: string;
    author: string;
}

interface Novel extends LiteraryWork {
    pageCount: number;
}

const warAndPeace: Novel = {
    title: 'War and Peace',
    author: 'Leo Tolstoy',
    pageCount: 1225
};

console.log(warAndPeace.pageCount); // 1225

The meandering river of inheritance finds its path: interfaces extending interfaces, compiling libraries of traits that can be bound to literary offspring in a manner most graceful.

Hybrid Types and Advanced Mischief

interface Player {
    (startCommand: string): void;
    game: string;
    score: number;
    updateScore(points: number): void;
}

const tableTennisPlayer: Player = {
    game: 'Table Tennis',
    score: 0,
    updateScore(points) {
        this.score += points;
    },
    (startCommand) {
        console.log(`Game Start: ${startCommand}`);
    }
};

tableTennisPlayer('Serve');
tableTennisPlayer.updateScore(1);
console.log(tableTennisPlayer.score); // 1

In a denouement steeped in advanced types, hybrid interfaces encounter scenarios fit to riddle even the sharpest Don, yet their solutions come as easily as paddling down the great river of type declarations.

Conclusion

Foresters of type, we have wandered this Old Ridged Forest of TypeScript interfaces with purposeful stride. Through groves basic and dales complex, we have pared down treachery with each clever step.

With quill put to rest, one can now peacefully draft with the knowledge of interfaces you’ve so valiantly gained—for no TypeScript scallywag shall you be, but rather a commander of types so true.