Prerequisites
- Basic TypeScript types understanding ๐
- JavaScript objects knowledge โก
- Interface basics helpful ๐ป
What you'll learn
- Create and use object types effectively ๐ฏ
- Master type aliases for reusability ๐๏ธ
- Build complex type compositions ๐
- Apply object types in real projects โจ
๐ฏ Introduction
Welcome to the architectural wonderland of TypeScript object types and type aliases! ๐ In this guide, weโll explore how to build rock-solid data structures that make your code a joy to work with.
Think of object types as blueprints for your data ๐ - they define the shape and structure of your objects. Type aliases are like custom labels ๐ท๏ธ that you can slap on any type to make it reusable and meaningful. Together, theyโre your power tools for creating maintainable, type-safe applications!
By the end of this tutorial, youโll be crafting elegant type systems that make your teammates say โWow!โ Letโs build! ๐โโ๏ธ
๐ Understanding Object Types and Type Aliases
๐ค What Are Object Types?
Object types in TypeScript are like detailed floor plans ๐ for your data structures. They specify exactly what properties an object should have and what types those properties should be.
Object types give you:
- โจ Precise structure definition
- ๐ IntelliSense superpowers
- ๐ก๏ธ Compile-time safety
- ๐ Self-documenting code
๐ก What Are Type Aliases?
Type aliases are your personal naming system ๐ท๏ธ for types. Instead of repeating complex type definitions, you create a friendly name that you can reuse everywhere!
// ๐จ Without type alias - repetitive and hard to maintain
let user1: { name: string; age: number; email: string };
let user2: { name: string; age: number; email: string };
// โจ With type alias - clean and reusable!
type User = { name: string; age: number; email: string };
let user1: User;
let user2: User;
๐ง Object Type Basics
๐ Creating Object Types
Letโs start with the fundamentals:
// ๐ฏ Basic object type inline
let person: { name: string; age: number } = {
name: "Sarah",
age: 28
};
// ๐๏ธ Type alias for reusability
type Person = {
name: string;
age: number;
email: string;
isActive: boolean;
};
// โจ Using the type
const developer: Person = {
name: "Alex Chen",
age: 32,
email: "[email protected]",
isActive: true
};
// ๐จ Optional properties with ?
type Product = {
id: string;
name: string;
price: number;
description?: string; // Optional
inStock?: boolean; // Optional
};
const laptop: Product = {
id: "PROD-001",
name: "TypeScript Laptop",
price: 999.99
// description and inStock are optional!
};
// ๐ Readonly properties
type Config = {
readonly apiUrl: string;
readonly apiKey: string;
readonly maxRetries: number;
};
const config: Config = {
apiUrl: "https://api.example.com",
apiKey: "secret-key-123",
maxRetries: 3
};
// config.apiUrl = "new-url"; // Error! Cannot assign to readonly property
๐ฎ Nested Object Types
Objects can contain other objects:
// ๐ข Company structure
type Address = {
street: string;
city: string;
country: string;
postalCode: string;
};
type Company = {
name: string;
founded: number;
employees: number;
headquarters: Address; // Nested object type
branches: Address[]; // Array of objects
};
const techGiant: Company = {
name: "TypeScript Corp",
founded: 2012,
employees: 5000,
headquarters: {
street: "123 Type Safety Lane",
city: "Redmond",
country: "USA",
postalCode: "98052"
},
branches: [
{
street: "456 Generic Ave",
city: "London",
country: "UK",
postalCode: "SW1A 1AA"
},
{
street: "789 Interface Blvd",
city: "Tokyo",
country: "Japan",
postalCode: "100-0001"
}
]
};
// ๐ฎ Game character with nested stats
type Stats = {
health: number;
mana: number;
strength: number;
defense: number;
speed: number;
};
type Equipment = {
weapon: string;
armor: string;
accessory: string;
};
type GameCharacter = {
id: string;
name: string;
level: number;
class: "warrior" | "mage" | "archer";
stats: Stats;
equipment: Equipment;
inventory: string[];
emoji: string;
};
const hero: GameCharacter = {
id: "HERO-001",
name: "TypeScript Warrior",
level: 42,
class: "warrior",
stats: {
health: 1000,
mana: 100,
strength: 85,
defense: 70,
speed: 60
},
equipment: {
weapon: "Sword of Type Safety โ๏ธ",
armor: "Compiler's Plate Mail ๐ก๏ธ",
accessory: "Ring of IntelliSense ๐"
},
inventory: ["Health Potion ๐งช", "Mana Potion ๐", "Debug Scroll ๐"],
emoji: "๐ฆธ"
};
๐ก Advanced Type Aliases
๐ Union Type Aliases
Combine multiple types into one:
// ๐ฏ Status types
type LoadingState = "idle" | "loading" | "success" | "error";
// ๐จ Flexible ID type
type ID = string | number;
// ๐ฆ API Response
type ApiResponse<T> =
| { status: "success"; data: T }
| { status: "error"; error: string }
| { status: "loading" };
// Using the union type
function handleResponse(response: ApiResponse<User>) {
switch (response.status) {
case "success":
console.log(`โ
Welcome, ${response.data.name}!`);
break;
case "error":
console.log(`โ Error: ${response.error}`);
break;
case "loading":
console.log("โณ Loading...");
break;
}
}
// ๐ฎ Game events
type GameEvent =
| { type: "player-join"; playerId: string; timestamp: Date }
| { type: "player-leave"; playerId: string; reason: string }
| { type: "score-update"; playerId: string; points: number }
| { type: "game-over"; winner: string; finalScores: Record<string, number> };
function processGameEvent(event: GameEvent) {
console.log(`๐ฎ Event: ${event.type}`);
switch (event.type) {
case "player-join":
console.log(`๐ ${event.playerId} joined the game!`);
break;
case "score-update":
console.log(`๐ฏ ${event.playerId} scored ${event.points} points!`);
break;
case "game-over":
console.log(`๐ Game Over! Winner: ${event.winner}`);
break;
}
}
๐๏ธ Intersection Type Aliases
Combine types to create more complex ones:
// ๐จ Base types
type Timestamped = {
createdAt: Date;
updatedAt: Date;
};
type Identifiable = {
id: string;
};
type Authorable = {
authorId: string;
authorName: string;
};
// ๐๏ธ Combining with intersections
type BlogPost = Identifiable & Timestamped & Authorable & {
title: string;
content: string;
tags: string[];
published: boolean;
views: number;
};
const myPost: BlogPost = {
id: "POST-001",
createdAt: new Date("2024-01-01"),
updatedAt: new Date("2024-01-15"),
authorId: "USER-123",
authorName: "TypeScript Enthusiast",
title: "Why Type Aliases Rock! ๐",
content: "Let me tell you about type aliases...",
tags: ["typescript", "programming", "web-dev"],
published: true,
views: 1337
};
// ๐ E-commerce example
type Priceable = {
price: number;
currency: string;
discount?: number;
};
type Shippable = {
weight: number;
dimensions: {
length: number;
width: number;
height: number;
};
shippingClass: "standard" | "express" | "overnight";
};
type DigitalProduct = Identifiable & Priceable & {
name: string;
downloadUrl: string;
fileSize: number;
format: string;
};
type PhysicalProduct = Identifiable & Priceable & Shippable & {
name: string;
stock: number;
manufacturer: string;
};
๐ฏ Generic Type Aliases
Make your types flexible and reusable:
// ๐ฆ Generic container
type Container<T> = {
value: T;
timestamp: Date;
metadata?: Record<string, unknown>;
};
// Using the generic
const numberContainer: Container<number> = {
value: 42,
timestamp: new Date()
};
const userContainer: Container<User> = {
value: { name: "Alice", age: 30, email: "[email protected]" },
timestamp: new Date(),
metadata: { source: "api", version: "2.0" }
};
// ๐ฎ Generic game state
type GameState<TPlayer, TItem> = {
players: TPlayer[];
items: TItem[];
scores: Record<string, number>;
currentRound: number;
isActive: boolean;
};
type Player = {
id: string;
name: string;
avatar: string;
};
type PowerUp = {
type: "speed" | "shield" | "damage";
duration: number;
power: number;
};
type MyGameState = GameState<Player, PowerUp>;
// ๐ Generic API pagination
type PaginatedResponse<T> = {
data: T[];
pagination: {
currentPage: number;
totalPages: number;
pageSize: number;
totalItems: number;
};
links: {
first: string;
last: string;
prev?: string;
next?: string;
};
};
const userList: PaginatedResponse<User> = {
data: [
{ name: "Alice", age: 30, email: "[email protected]" },
{ name: "Bob", age: 25, email: "[email protected]" }
],
pagination: {
currentPage: 1,
totalPages: 5,
pageSize: 2,
totalItems: 10
},
links: {
first: "/users?page=1",
last: "/users?page=5",
next: "/users?page=2"
}
};
๐ Practical Examples
๐ E-Commerce System
Letโs build a complete e-commerce type system:
// ๐๏ธ E-commerce type system
type Currency = "USD" | "EUR" | "GBP" | "JPY";
type PaymentMethod = "credit_card" | "paypal" | "crypto" | "bank_transfer";
type OrderStatus = "pending" | "processing" | "shipped" | "delivered" | "cancelled";
// ๐ฐ Money handling
type Money = {
amount: number;
currency: Currency;
};
// ๐๏ธ Product types
type BaseProduct = {
id: string;
sku: string;
name: string;
description: string;
price: Money;
images: string[];
categories: string[];
tags: string[];
};
type InventoryInfo = {
inStock: boolean;
quantity: number;
warehouse: string;
};
type PhysicalProductDetails = {
weight: number;
dimensions: {
length: number;
width: number;
height: number;
unit: "cm" | "inch";
};
requiresShipping: true;
};
type DigitalProductDetails = {
fileSize: number;
downloadUrl: string;
licenseKey?: string;
requiresShipping: false;
};
type PhysicalProduct = BaseProduct & InventoryInfo & PhysicalProductDetails;
type DigitalProduct = BaseProduct & DigitalProductDetails;
type Product = PhysicalProduct | DigitalProduct;
// ๐ Shopping cart
type CartItem = {
productId: string;
quantity: number;
selectedOptions?: Record<string, string>;
addedAt: Date;
};
type Cart = {
id: string;
userId: string;
items: CartItem[];
subtotal: Money;
tax: Money;
shipping: Money;
total: Money;
couponCode?: string;
discount?: Money;
};
// ๐ฆ Order system
type ShippingAddress = {
fullName: string;
addressLine1: string;
addressLine2?: string;
city: string;
state: string;
postalCode: string;
country: string;
phone: string;
};
type PaymentInfo = {
method: PaymentMethod;
transactionId: string;
amount: Money;
status: "pending" | "completed" | "failed";
processedAt?: Date;
};
type Order = {
id: string;
orderNumber: string;
userId: string;
items: Array<CartItem & { price: Money }>;
shippingAddress: ShippingAddress;
billingAddress: ShippingAddress;
payment: PaymentInfo;
status: OrderStatus;
tracking?: {
carrier: string;
trackingNumber: string;
estimatedDelivery: Date;
};
timestamps: {
created: Date;
updated: Date;
shipped?: Date;
delivered?: Date;
};
totals: {
subtotal: Money;
tax: Money;
shipping: Money;
discount?: Money;
total: Money;
};
};
// ๐ช Store implementation
class OnlineStore {
private products: Map<string, Product> = new Map();
private carts: Map<string, Cart> = new Map();
private orders: Map<string, Order> = new Map();
// ๐ฆ Add product to store
addProduct(product: Product): void {
this.products.set(product.id, product);
console.log(`โ
Added product: ${product.name}`);
}
// ๐ Create cart for user
createCart(userId: string): Cart {
const cart: Cart = {
id: `CART-${Date.now()}`,
userId,
items: [],
subtotal: { amount: 0, currency: "USD" },
tax: { amount: 0, currency: "USD" },
shipping: { amount: 0, currency: "USD" },
total: { amount: 0, currency: "USD" }
};
this.carts.set(cart.id, cart);
return cart;
}
// โ Add item to cart
addToCart(cartId: string, productId: string, quantity: number): void {
const cart = this.carts.get(cartId);
const product = this.products.get(productId);
if (!cart || !product) return;
const existingItem = cart.items.find(item => item.productId === productId);
if (existingItem) {
existingItem.quantity += quantity;
} else {
cart.items.push({
productId,
quantity,
addedAt: new Date()
});
}
this.updateCartTotals(cart);
console.log(`๐ Added ${quantity}x ${product.name} to cart`);
}
// ๐ฐ Update cart totals
private updateCartTotals(cart: Cart): void {
let subtotal = 0;
cart.items.forEach(item => {
const product = this.products.get(item.productId);
if (product) {
subtotal += product.price.amount * item.quantity;
}
});
cart.subtotal = { amount: subtotal, currency: "USD" };
cart.tax = { amount: subtotal * 0.08, currency: "USD" }; // 8% tax
cart.shipping = { amount: subtotal > 50 ? 0 : 10, currency: "USD" }; // Free shipping over $50
const total = subtotal + cart.tax.amount + cart.shipping.amount - (cart.discount?.amount || 0);
cart.total = { amount: total, currency: "USD" };
}
}
๐ฎ Game Development Types
Building a complete RPG game type system:
// ๐ฎ RPG Game Type System
type ElementType = "fire" | "water" | "earth" | "air" | "light" | "dark";
type CharacterClass = "warrior" | "mage" | "archer" | "healer" | "rogue";
type ItemRarity = "common" | "uncommon" | "rare" | "epic" | "legendary";
// ๐ก๏ธ Combat types
type DamageType = "physical" | "magical" | "true";
type CombatStats = {
attack: number;
defense: number;
magicPower: number;
magicDefense: number;
speed: number;
criticalRate: number;
criticalDamage: number;
};
// ๐ Item system
type BaseItem = {
id: string;
name: string;
description: string;
rarity: ItemRarity;
level: number;
value: number;
icon: string;
};
type EquipmentSlot = "weapon" | "helmet" | "armor" | "gloves" | "boots" | "accessory";
type Equipment = BaseItem & {
type: "equipment";
slot: EquipmentSlot;
stats: Partial<CombatStats>;
requirements: {
level?: number;
class?: CharacterClass;
strength?: number;
};
};
type Consumable = BaseItem & {
type: "consumable";
effect: {
heal?: number;
mana?: number;
buff?: Partial<CombatStats>;
duration?: number;
};
stackSize: number;
};
type QuestItem = BaseItem & {
type: "quest";
questId: string;
};
type GameItem = Equipment | Consumable | QuestItem;
// ๐ฆธ Character system
type CharacterBase = {
id: string;
name: string;
level: number;
experience: number;
class: CharacterClass;
element: ElementType;
};
type CharacterVitals = {
health: number;
maxHealth: number;
mana: number;
maxMana: number;
stamina: number;
maxStamina: number;
};
type CharacterEquipment = {
[K in EquipmentSlot]?: Equipment;
};
type CharacterInventory = {
items: GameItem[];
gold: number;
capacity: number;
};
type Character = CharacterBase & {
vitals: CharacterVitals;
stats: CombatStats;
equipment: CharacterEquipment;
inventory: CharacterInventory;
skills: Skill[];
quests: Quest[];
};
// โ๏ธ Skill system
type SkillEffect = {
damage?: number;
heal?: number;
buff?: Partial<CombatStats>;
debuff?: Partial<CombatStats>;
duration?: number;
};
type Skill = {
id: string;
name: string;
description: string;
icon: string;
manaCost: number;
cooldown: number;
range: number;
areaOfEffect?: number;
effects: SkillEffect[];
requirements: {
level: number;
class: CharacterClass;
};
};
// ๐ Quest system
type QuestObjective =
| { type: "kill"; enemyId: string; count: number; current: number }
| { type: "collect"; itemId: string; count: number; current: number }
| { type: "talk"; npcId: string; completed: boolean }
| { type: "reach"; location: string; completed: boolean };
type QuestReward = {
experience: number;
gold: number;
items?: GameItem[];
skills?: Skill[];
};
type Quest = {
id: string;
name: string;
description: string;
level: number;
objectives: QuestObjective[];
rewards: QuestReward;
status: "available" | "active" | "completed" | "failed";
prerequisites?: string[]; // Quest IDs
};
// ๐ฏ Game implementation
class RPGGame {
private characters: Map<string, Character> = new Map();
private items: Map<string, GameItem> = new Map();
// ๐ฆธ Create character
createCharacter(name: string, characterClass: CharacterClass): Character {
const baseStats: CombatStats = this.getBaseStats(characterClass);
const character: Character = {
id: `CHAR-${Date.now()}`,
name,
level: 1,
experience: 0,
class: characterClass,
element: "fire", // Default element
vitals: {
health: 100,
maxHealth: 100,
mana: 50,
maxMana: 50,
stamina: 100,
maxStamina: 100
},
stats: baseStats,
equipment: {},
inventory: {
items: [],
gold: 100,
capacity: 20
},
skills: [],
quests: []
};
this.characters.set(character.id, character);
console.log(`๐ฆธ Created ${characterClass} named ${name}!`);
return character;
}
// โ๏ธ Equip item
equipItem(characterId: string, item: Equipment): boolean {
const character = this.characters.get(characterId);
if (!character) return false;
// Check requirements
if (item.requirements.level && character.level < item.requirements.level) {
console.log(`โ Level ${item.requirements.level} required!`);
return false;
}
if (item.requirements.class && character.class !== item.requirements.class) {
console.log(`โ ${item.requirements.class} class required!`);
return false;
}
// Unequip current item in slot
const currentItem = character.equipment[item.slot];
if (currentItem) {
character.inventory.items.push(currentItem);
}
// Equip new item
character.equipment[item.slot] = item;
// Update stats
this.updateCharacterStats(character);
console.log(`โ
Equipped ${item.name}!`);
return true;
}
// ๐ Update character stats
private updateCharacterStats(character: Character): void {
const baseStats = this.getBaseStats(character.class);
const equipmentStats: Partial<CombatStats> = {};
// Calculate equipment bonuses
Object.values(character.equipment).forEach(item => {
if (item) {
Object.entries(item.stats).forEach(([stat, value]) => {
equipmentStats[stat as keyof CombatStats] =
(equipmentStats[stat as keyof CombatStats] || 0) + value;
});
}
});
// Apply bonuses to base stats
character.stats = {
attack: baseStats.attack + (equipmentStats.attack || 0),
defense: baseStats.defense + (equipmentStats.defense || 0),
magicPower: baseStats.magicPower + (equipmentStats.magicPower || 0),
magicDefense: baseStats.magicDefense + (equipmentStats.magicDefense || 0),
speed: baseStats.speed + (equipmentStats.speed || 0),
criticalRate: baseStats.criticalRate + (equipmentStats.criticalRate || 0),
criticalDamage: baseStats.criticalDamage + (equipmentStats.criticalDamage || 0)
};
}
// ๐ฏ Get base stats by class
private getBaseStats(characterClass: CharacterClass): CombatStats {
const statsMap: Record<CharacterClass, CombatStats> = {
warrior: { attack: 15, defense: 20, magicPower: 5, magicDefense: 10, speed: 8, criticalRate: 0.1, criticalDamage: 1.5 },
mage: { attack: 5, defense: 10, magicPower: 20, magicDefense: 15, speed: 10, criticalRate: 0.15, criticalDamage: 1.75 },
archer: { attack: 12, defense: 12, magicPower: 8, magicDefense: 12, speed: 15, criticalRate: 0.2, criticalDamage: 2.0 },
healer: { attack: 8, defense: 12, magicPower: 15, magicDefense: 18, speed: 10, criticalRate: 0.1, criticalDamage: 1.25 },
rogue: { attack: 18, defense: 8, magicPower: 10, magicDefense: 8, speed: 20, criticalRate: 0.25, criticalDamage: 2.5 }
};
return statsMap[characterClass];
}
}
โ ๏ธ Common Pitfalls and Solutions
๐ฑ Pitfall 1: Type vs Interface Confusion
// โ Using type for everything
type User = {
name: string;
age: number;
};
type Admin = User & { // Can't use extends!
permissions: string[];
};
// โ
Use interface for object shapes that might be extended
interface User {
name: string;
age: number;
}
interface Admin extends User {
permissions: string[];
}
// โ
Use type for unions, primitives, and utilities
type ID = string | number;
type Status = "active" | "inactive";
type Nullable<T> = T | null;
๐คฏ Pitfall 2: Nested Object Typing
// โ Inline nested types - hard to read and maintain
type Company = {
name: string;
address: {
street: string;
city: string;
location: {
lat: number;
lng: number;
};
};
};
// โ
Extract nested types for clarity
type Coordinates = {
lat: number;
lng: number;
};
type Address = {
street: string;
city: string;
location: Coordinates;
};
type Company = {
name: string;
address: Address;
};
๐ต Pitfall 3: Optional vs Undefined
// โ Confusing optional and undefined
type Config = {
apiUrl?: string; // Can be undefined OR missing
timeout: number | undefined; // Must be present but can be undefined
};
// This is valid for the first but not the second
const config1: Config = {
timeout: undefined
};
// โ
Be clear about intent
type Config = {
apiUrl?: string; // Truly optional
timeout: number; // Always required
retries?: number; // Optional with default
};
function createConfig(partial: Partial<Config>): Config {
return {
timeout: 5000, // Required, provide default
retries: 3, // Optional with default
...partial // Override with provided values
};
}
๐ ๏ธ Best Practices
๐ฏ Object Type Best Practices
-
๐ Use Descriptive Names: Make intent crystal clear
// โ Vague names type Data = { x: number; y: number }; // โ Descriptive names type CartesianPoint = { x: number; y: number };
-
๐๏ธ Compose Types: Build complex types from simple ones
type Timestamp = { createdAt: Date; updatedAt: Date }; type Identifiable = { id: string }; type User = Identifiable & Timestamp & { name: string; email: string; };
-
๐จ Use Type Aliases for Clarity: Even for simple types
type UserID = string; type Email = string; type Age = number; type User = { id: UserID; email: Email; age: Age; };
-
โจ Leverage Utility Types: Donโt reinvent the wheel
type User = { id: string; name: string; email: string; age: number; }; type PartialUser = Partial<User>; type ReadonlyUser = Readonly<User>; type UserWithoutEmail = Omit<User, "email">;
-
๐ก๏ธ Use Readonly for Immutability: Prevent accidental mutations
type ImmutableConfig = Readonly<{ apiUrl: string; apiKey: string; features: ReadonlyArray<string>; }>;
๐งช Hands-On Exercise
๐ฏ Challenge: Build a Social Media Type System
Create a complete type system for a social media platform:
๐ Requirements:
- โ User profiles with detailed information
- ๐ท๏ธ Different post types (text, image, video)
- ๐ฅ Comments and reactions system
- ๐ Event and group types
- ๐จ Privacy settings and permissions
๐ Bonus Points:
- Add notification types
- Implement messaging system types
- Create analytics data types
๐ก Solution
๐ Click to see solution
// ๐ Social Media Platform Type System
// ๐ Basic ID types
type UserID = string;
type PostID = string;
type CommentID = string;
type GroupID = string;
type EventID = string;
// ๐ Privacy types
type PrivacySetting = "public" | "friends" | "friends-of-friends" | "private";
type ReactionType = "like" | "love" | "haha" | "wow" | "sad" | "angry";
// ๐
Timestamp tracking
type Timestamps = {
createdAt: Date;
updatedAt: Date;
deletedAt?: Date;
};
// ๐ค User system
type UserProfile = {
id: UserID;
username: string;
displayName: string;
email: string;
avatar?: string;
coverPhoto?: string;
bio?: string;
location?: string;
website?: string;
birthday?: Date;
joinedAt: Date;
};
type UserSettings = {
privacy: {
profileVisibility: PrivacySetting;
friendListVisibility: PrivacySetting;
emailVisibility: PrivacySetting;
birthdayVisibility: PrivacySetting;
};
notifications: {
email: boolean;
push: boolean;
sms: boolean;
frequency: "instant" | "daily" | "weekly";
};
theme: "light" | "dark" | "auto";
};
type User = UserProfile & {
settings: UserSettings;
stats: {
friendsCount: number;
followersCount: number;
followingCount: number;
postsCount: number;
};
verified: boolean;
status: "active" | "suspended" | "deactivated";
};
// ๐ Post system
type BasePost = Timestamps & {
id: PostID;
authorId: UserID;
content: string;
privacy: PrivacySetting;
tags: string[];
mentions: UserID[];
location?: {
name: string;
coordinates?: { lat: number; lng: number };
};
edited: boolean;
editHistory?: Array<{
content: string;
editedAt: Date;
}>;
};
type TextPost = BasePost & {
type: "text";
};
type ImagePost = BasePost & {
type: "image";
images: Array<{
url: string;
width: number;
height: number;
alt?: string;
}>;
};
type VideoPost = BasePost & {
type: "video";
video: {
url: string;
duration: number;
thumbnail: string;
width: number;
height: number;
};
};
type PollPost = BasePost & {
type: "poll";
poll: {
question: string;
options: Array<{
id: string;
text: string;
votes: number;
}>;
endsAt: Date;
multipleChoice: boolean;
};
};
type Post = TextPost | ImagePost | VideoPost | PollPost;
// ๐ฌ Interaction system
type Comment = Timestamps & {
id: CommentID;
postId: PostID;
authorId: UserID;
content: string;
parentId?: CommentID; // For nested comments
mentions: UserID[];
edited: boolean;
};
type Reaction = {
userId: UserID;
type: ReactionType;
timestamp: Date;
};
type PostEngagement = {
postId: PostID;
reactions: Reaction[];
comments: Comment[];
shares: Array<{
userId: UserID;
timestamp: Date;
message?: string;
}>;
views: number;
};
// ๐ฅ Group system
type Group = Timestamps & {
id: GroupID;
name: string;
description: string;
coverPhoto?: string;
privacy: "public" | "private" | "secret";
members: Array<{
userId: UserID;
role: "admin" | "moderator" | "member";
joinedAt: Date;
}>;
rules?: string[];
categories: string[];
settings: {
postApproval: boolean;
memberApproval: boolean;
allowedPostTypes: Post["type"][];
};
};
// ๐
Event system
type Event = Timestamps & {
id: EventID;
name: string;
description: string;
coverPhoto?: string;
startDate: Date;
endDate: Date;
location: {
type: "physical" | "virtual" | "hybrid";
address?: string;
coordinates?: { lat: number; lng: number };
virtualLink?: string;
};
organizer: UserID;
coHosts: UserID[];
privacy: PrivacySetting;
attendees: Array<{
userId: UserID;
status: "going" | "interested" | "not-going";
respondedAt: Date;
}>;
capacity?: number;
ticketPrice?: number;
categories: string[];
};
// ๐ฌ Notification system
type BaseNotification = {
id: string;
recipientId: UserID;
read: boolean;
timestamp: Date;
};
type NotificationType =
| { type: "friend-request"; from: UserID }
| { type: "post-reaction"; postId: PostID; reaction: ReactionType; from: UserID }
| { type: "comment"; postId: PostID; commentId: CommentID; from: UserID }
| { type: "mention"; postId: PostID; from: UserID }
| { type: "group-invite"; groupId: GroupID; from: UserID }
| { type: "event-invite"; eventId: EventID; from: UserID }
| { type: "birthday"; userId: UserID }
| { type: "memory"; postId: PostID; yearsAgo: number };
type Notification = BaseNotification & NotificationType;
// ๐ฌ Messaging system
type Conversation = Timestamps & {
id: string;
participants: UserID[];
lastMessage?: {
content: string;
senderId: UserID;
timestamp: Date;
};
unreadCounts: Record<UserID, number>;
};
type Message = Timestamps & {
id: string;
conversationId: string;
senderId: UserID;
content: string;
attachments?: Array<{
type: "image" | "video" | "file";
url: string;
name: string;
size: number;
}>;
readBy: Array<{
userId: UserID;
readAt: Date;
}>;
reactions: Reaction[];
};
// ๐ Analytics types
type UserAnalytics = {
userId: UserID;
period: "day" | "week" | "month" | "year";
metrics: {
profileViews: number;
postViews: number;
engagement: {
reactions: Record<ReactionType, number>;
comments: number;
shares: number;
};
followerGrowth: number;
topPosts: PostID[];
};
};
// ๐๏ธ Implementation
class SocialMediaPlatform {
private users: Map<UserID, User> = new Map();
private posts: Map<PostID, Post> = new Map();
private groups: Map<GroupID, Group> = new Map();
private events: Map<EventID, Event> = new Map();
// ๐ค Create user
createUser(profile: Omit<UserProfile, "id" | "joinedAt">): User {
const user: User = {
id: `USER-${Date.now()}`,
joinedAt: new Date(),
...profile,
settings: {
privacy: {
profileVisibility: "public",
friendListVisibility: "friends",
emailVisibility: "private",
birthdayVisibility: "friends"
},
notifications: {
email: true,
push: true,
sms: false,
frequency: "instant"
},
theme: "auto"
},
stats: {
friendsCount: 0,
followersCount: 0,
followingCount: 0,
postsCount: 0
},
verified: false,
status: "active"
};
this.users.set(user.id, user);
console.log(`๐ค Welcome ${user.displayName} (@${user.username})!`);
return user;
}
// ๐ Create post
createPost(authorId: UserID, postData: Omit<Post, "id" | "authorId" | "createdAt" | "updatedAt" | "edited">): Post {
const basePost = {
id: `POST-${Date.now()}` as PostID,
authorId,
createdAt: new Date(),
updatedAt: new Date(),
edited: false,
...postData
};
const post = basePost as Post;
this.posts.set(post.id, post);
// Update user's post count
const user = this.users.get(authorId);
if (user) {
user.stats.postsCount++;
}
console.log(`๐ New ${post.type} post created!`);
return post;
}
// ๐ฌ Add reaction
addReaction(postId: PostID, userId: UserID, type: ReactionType): void {
const post = this.posts.get(postId);
if (!post) return;
console.log(`${this.getReactionEmoji(type)} ${userId} reacted to post!`);
}
// ๐ฏ Get reaction emoji
private getReactionEmoji(type: ReactionType): string {
const emojiMap: Record<ReactionType, string> = {
like: "๐",
love: "โค๏ธ",
haha: "๐",
wow: "๐ฎ",
sad: "๐ข",
angry: "๐ "
};
return emojiMap[type];
}
}
// ๐ฎ Test the system
const platform = new SocialMediaPlatform();
// Create users
const alice = platform.createUser({
username: "alice_dev",
displayName: "Alice Chen",
email: "[email protected]",
bio: "TypeScript enthusiast ๐",
location: "San Francisco, CA"
});
const bob = platform.createUser({
username: "bob_coder",
displayName: "Bob Smith",
email: "[email protected]",
bio: "Full-stack developer ๐"
});
// Create posts
const textPost = platform.createPost(alice.id, {
type: "text",
content: "Just learned about TypeScript object types! Mind = blown ๐คฏ",
privacy: "public",
tags: ["typescript", "learning", "webdev"],
mentions: [bob.id]
});
const imagePost = platform.createPost(bob.id, {
type: "image",
content: "Check out my new TypeScript setup! ๐",
privacy: "friends",
tags: ["coding", "setup"],
mentions: [],
images: [{
url: "https://example.com/setup.jpg",
width: 1920,
height: 1080,
alt: "My TypeScript development setup"
}]
});
// Add reactions
platform.addReaction(textPost.id, bob.id, "love");
platform.addReaction(imagePost.id, alice.id, "wow");
๐ Key Takeaways
Youโve mastered object types and type aliases in TypeScript! Hereโs what you can now do:
- โ Create complex object types with confidence ๐ช
- โ Use type aliases for cleaner, reusable code ๐ฏ
- โ Compose types with unions and intersections ๐๏ธ
- โ Build generic types for maximum flexibility ๐
- โ Design real-world type systems like a pro! ๐
Remember: Object types and type aliases are your building blocks for creating maintainable, type-safe applications. Start simple, compose wisely! ๐ค
๐ค Next Steps
Congratulations! ๐ Youโve become an object types and type aliases master!
Hereโs what to do next:
- ๐ป Complete the social media exercise
- ๐๏ธ Refactor existing code to use type aliases
- ๐ Learn about function types and parameters
- ๐ Explore advanced generic patterns!
Remember: Great type systems make great applications. Keep building! ๐
Happy coding! ๐๐โจ