TypeScript Interfaces
Interfaces define the shape of objects. They act as contracts that objects must follow.
Basic Syntax
interface Person {
name: string;
age: number;
greet(): void;
}
let user: Person = {
name: "John",
age: 25,
greet() {
console.log(`Hi, I'm ${this.name}`);
}
};
Why interfaces? TypeScript checks that objects match the defined structure.
Optional Properties
Use ? for properties that may be missing:
interface Car {
make: string;
model: string;
year?: number;
}
let myCar: Car = { make: "Toyota", model: "Camry" }; // OK
Readonly Properties
readonly properties can only be set at creation:
interface Config {
readonly id: string;
name: string;
}
let config: Config = { id: "abc", name: "MyApp" };
// config.id = "new"; // Error: read-only
config.name = "New"; // OK
Methods
Define method signatures without implementation:
interface Calculator {
add(a: number, b: number): number;
subtract(a: number, b: number): number;
}
let calc: Calculator = {
add(a, b) { return a + b; },
subtract(a, b) { return a - b; }
};
Extending Interfaces
Inherit properties from other interfaces:
interface Animal {
name: string;
age: number;
}
interface Dog extends Animal {
breed: string;
bark(): void;
}
let myDog: Dog = {
name: "Buddy",
age: 3,
breed: "Labrador",
bark() { console.log("Woof!"); }
};
Tip: An interface can extend multiple interfaces: interface X extends A, B {}.
Interface vs Type Alias
// Interface — can be merged and extended
interface User { name: string; }
interface User { age: number; } // Declaration merging
// Type alias — cannot be re-declared
type UserType = { name: string; };
// type UserType = { age: number; } // Error
Remember: Use interfaces for object shapes. Use type aliases for unions and intersections.
Best Practices
- Use interfaces for object shapes that may be extended
- Use optional properties sparingly
- Extend interfaces instead of duplicating properties
- Keep interfaces focused — one responsibility each
Common Mistakes
- Using type aliases where interfaces would be more flexible
- Forgetting optional markers on properties
- Not using
implementswith classes - Over-nesting interface extensions