TypeScript Interfaces

Define contracts for object structures

๐Ÿ“‹ What are Interfaces?

Interfaces define the structure of objects by specifying property names and types. They act as contracts ensuring objects have required properties, making your code predictable and type-safe throughout your application.


// Simple interface
interface User {
    name: string;
    age: number;
}

let person: User = { name: "Alice", age: 25 };
                                    

Interface Features

โœ…

Required Properties

Must be present in objects

interface Product {
    name: string;
    price: number;
}
โ“

Optional Properties

May or may not exist

interface User {
    name: string;
    email?: string;
}
๐Ÿ”’

Readonly Properties

Cannot be modified

interface Config {
    readonly apiKey: string;
}
๐Ÿ”„

Extending Interfaces

Inherit from other interfaces

interface Admin 
    extends User {
    role: string;
}

๐Ÿ”น Basic Interface

Define the structure of an object:

interface Book {
    title: string;
    author: string;
    pages: number;
}

let myBook: Book = {
    title: "TypeScript Guide",
    author: "John Doe",
    pages: 350
};

console.log(`${myBook.title} by ${myBook.author}`);
console.log(`Pages: ${myBook.pages}`);

Output:

TypeScript Guide by John Doe

Pages: 350

๐Ÿ”น Optional Properties

Use ? to make properties optional:

interface Person {
    name: string;
    age: number;
    email?: string;  // Optional
    phone?: string;  // Optional
}

let user1: Person = {
    name: "Alice",
    age: 28,
    email: "[email protected]"
};

let user2: Person = {
    name: "Bob",
    age: 32
    // email and phone are optional
};

console.log(user1.name);
console.log(user2.name);

Output:

Alice

Bob

๐Ÿ”น Readonly Properties

Prevent modification after creation:

interface DatabaseConfig {
    readonly host: string;
    readonly port: number;
    database: string;
}

let config: DatabaseConfig = {
    host: "localhost",
    port: 5432,
    database: "myapp"
};

console.log(`Connecting to ${config.host}:${config.port}`);

// config.host = "newhost"; // Error: Cannot assign to 'host'
config.database = "newdb"; // OK - not readonly

Output:

Connecting to localhost:5432

๐Ÿ”น Function Properties

Interfaces can include method signatures:

interface Calculator {
    add(a: number, b: number): number;
    subtract(a: number, b: number): number;
}

let calc: Calculator = {
    add: (a, b) => a + b,
    subtract: (a, b) => a - b
};

console.log(calc.add(10, 5));
console.log(calc.subtract(10, 5));

Output:

15

5

๐Ÿ”น Extending Interfaces

Create new interfaces based on existing ones:

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

interface Dog extends Animal {
    breed: string;
    bark(): void;
}

let myDog: Dog = {
    name: "Buddy",
    age: 3,
    breed: "Golden Retriever",
    bark: () => console.log("Woof!")
};

console.log(`${myDog.name} is a ${myDog.breed}`);
myDog.bark();

Output:

Buddy is a Golden Retriever

Woof!

๐Ÿ”น Multiple Interface Extension

Extend multiple interfaces at once:

interface Nameable {
    name: string;
}

interface Ageable {
    age: number;
}

interface Employee extends Nameable, Ageable {
    employeeId: string;
    department: string;
}

let employee: Employee = {
    name: "Sarah",
    age: 29,
    employeeId: "E123",
    department: "Engineering"
};

console.log(`${employee.name} works in ${employee.department}`);

Output:

Sarah works in Engineering

๐Ÿ”น Index Signatures

Allow dynamic property names:

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

let translations: StringDictionary = {
    hello: "Hola",
    goodbye: "Adiรณs",
    thanks: "Gracias"
};

console.log(translations.hello);
console.log(translations["goodbye"]);

Output:

Hola

Adiรณs

๐Ÿ”น Practical Example

Building a blog post system with interfaces:

interface Author {
    name: string;
    email: string;
}

interface Post {
    id: number;
    title: string;
    content: string;
    author: Author;
    published: boolean;
}

interface Blog {
    posts: Post[];
    addPost(post: Post): void;
}

let myBlog: Blog = {
    posts: [],
    addPost(post) {
        this.posts.push(post);
        console.log(`Added: ${post.title}`);
    }
};

let newPost: Post = {
    id: 1,
    title: "Learning TypeScript",
    content: "TypeScript is amazing!",
    author: { name: "Alice", email: "[email protected]" },
    published: true
};

myBlog.addPost(newPost);

Output:

Added: Learning TypeScript

๐Ÿง  Test Your Knowledge

How do you make a property optional in an interface?