Objects & Interfaces
Structuring Complex Data
Open interactive version (quiz + challenge)Real-world analogy
Objects are like student ID cards — they have labeled fields (name, age, email). Interfaces are like the ID card DESIGN — they say 'every card MUST have these fields with these types.' Separate objects follow the same design!
What is it?
Objects are collections of key-value pairs. Interfaces define the expected shape of an object — what properties it must have and their types. A well-defined interface prevents bugs by ensuring objects have the required structure.
Real-world relevance
Every API response is an object. Every database record is an object. Learning to design good interfaces is one of the most important skills in TypeScript!
Key points
- Objects as Key-Value Bags — Objects store multiple pieces of info about ONE thing. { name: 'John', age: 25, email: 'j@m.com' }. Access with dot notation: user.name or user['name'].
- Interfaces Define Shapes — interface User { name: string; age: number; } tells TypeScript 'a User MUST have name and age with these types.' Any object claiming to be a User must match this shape.
- Optional Properties with ? — interface User { name: string; email?: string } means email CAN be missing. Required = must exist. Optional = might not exist.
- Readonly Properties — interface Config { readonly apiUrl: string } means you can READ it but never CHANGE it. Great for constants!
- Type vs Interface — Both define shapes but use them differently: interface for objects (most common), type for unions/literals/functions. Interface can be extended; type uses intersection (&).
- Extending Interfaces — interface Dog extends Animal { breed: string } means Dog has everything Animal has PLUS breed. Inheritance = less repetition!
- Nested Interfaces — Objects inside objects: { user: { name: string; address: { city: string; country: string } } }. Build complex shapes by nesting!
- Index Signatures for Dynamic Keys — interface Colors { [key: string]: string } means you can have ANY string key with string values. Perfect when keys aren't known in advance!
Code example
// Simple object
const user = {
name: "John",
age: 25,
email: "john@mail.com"
};
// Access values
user.name; // "John"
user["age"]; // 25 (bracket notation)
// Change values (const allows changing INSIDE)
user.age = 26; // OK!
// Define shape with interface
interface User {
id: string;
name: string;
age: number;
email: string;
phone?: string; // ? = optional
readonly createdAt: Date; // cannot change
}
// Use the interface
const john: User = {
id: "1",
name: "John",
age: 25,
email: "john@mail.com",
// phone is optional — OK to skip!
createdAt: new Date()
};
// Extending interfaces — inheritance!
interface Animal {
name: string;
age: number;
}
interface Dog extends Animal {
breed: string;
}
const dog: Dog = {
name: "Rex",
age: 5,
breed: "Labrador"
};
// Nested interfaces
interface Address {
street: string;
city: string;
country: string;
}
interface Person {
name: string;
address: Address;
friends: Person[]; // array of Persons!
}
// Type vs Interface
type Status = "active" | "inactive"; // type for unions
type Callback = (x: number) => void; // type for functions
interface Config { // interface for objects
apiUrl: string;
port: number;
}
// Index signatures — unknown keys
interface ColorMap {
[colorName: string]: string;
}
const colors: ColorMap = {
red: "#FF0000",
blue: "#0000FF",
green: "#00FF00"
};Line-by-line walkthrough
- 1. Simple object
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8. Access values
- 9.
- 10.
- 11.
- 12. Change values (const allows changing INSIDE)
- 13.
- 14.
- 15. Define shape with interface
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25. Use the interface
- 26.
- 27.
- 28.
- 29.
- 30.
- 31. phone is optional — OK to skip!
- 32.
- 33.
- 34.
- 35. Extending interfaces — inheritance!
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51. Nested interfaces
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64. Type vs Interface
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72. Index signatures — unknown keys
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
Spot the bug
interface User {
name: string;
age: number;
}
const user: User = {
name: "Alice",
age: "twenty-five"
};Need a hint?
Check if the value types match what the interface expects...
Show answer
The interface says 'age' must be a number, but 'twenty-five' is a string. Fix: change the value to a number like 25.
Explain like I'm 5
Objects are like your student ID card - it has labeled spots for your name, age, and photo. An interface is like the blank ID card template that says 'every card MUST have these spots.' If you forget to fill in your name, someone says 'Hey, you missed a spot!'
Fun fact
The term 'structural typing' means TypeScript checks the SHAPE of objects, not their name. If it looks like a duck and quacks like a duck, TypeScript treats it as a duck!
Hands-on challenge
Design an interface for a Product (name, price, description, imageUrl, inStock). Then create 3 product objects and use them in an array!
More resources
- TypeScript Handbook - Object Types (TypeScript Official)
- TypeScript Interfaces (TypeScript Official)
- TypeScript Interfaces Explained (Web Dev Simplified)