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