Prerequisites
- Class inheritance basics ๐๏ธ
- Constructor understanding ๐ง
- Method definitions ๐
What you'll learn
- Understand super keyword fundamentals ๐ฏ
- Call parent constructors properly โก
- Access parent methods effectively ๐
- Handle method overriding scenarios ๐
๐ฏ Introduction
Welcome to the super-powered world of the super
keyword! ๐ In this guide, weโll explore one of the most important tools for working with inheritance in TypeScript: the ability to communicate with parent classes.
Youโll discover how super
acts like a bridge ๐ between child and parent classes, allowing you to access parent constructors and methods. Whether youโre building complex class hierarchies ๐๏ธ or extending existing functionality ๐ง, understanding super
is essential for writing clean, maintainable code.
By the end of this tutorial, youโll be a super expert at using super
! Letโs dive in! ๐โโ๏ธ
๐ Understanding the Super Keyword
๐ค What is Super?
The super
keyword is like a telephone ๐ that lets you call your parent class directly. Think of it as a way to say โHey parent, I need to use your functionality!โ
In TypeScript terms, super
allows you to:
- โจ Call the parent class constructor
- ๐ Access parent class methods
- ๐ก๏ธ Extend parent functionality without losing it
- ๐ง Coordinate between parent and child classes
๐ก Why Use Super?
Hereโs why developers love the super
keyword:
- Code Reuse โป๏ธ: Donโt rewrite what already works
- Proper Initialization ๐ฏ: Ensure parent setup happens first
- Method Enhancement ๐: Extend rather than replace functionality
- Clean Architecture ๐๏ธ: Maintain clear class relationships
Real-world example: Imagine building a notification system ๐ฑ. Your base Notification
class handles basic setup, while EmailNotification
uses super()
to initialize the base, then adds email-specific features.
๐ง Basic Syntax and Usage
๐ Constructor Super Calls
Letโs start with the most common use of super
:
// ๐ค Base person class
class Person {
name: string;
age: number;
id: string;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
this.id = Math.random().toString(36).substring(2, 9); // ๐ฒ Random ID
console.log(`๐ค Person created: ${this.name} (ID: ${this.id})`);
}
// ๐ Basic greeting
greet(): string {
return `Hello, I'm ${this.name}! ๐`;
}
// ๐ Get basic info
getInfo(): string {
return `${this.name}, age ${this.age} (ID: ${this.id})`;
}
}
// ๐จโ๐ผ Employee extends Person
class Employee extends Person {
jobTitle: string;
salary: number;
constructor(name: string, age: number, jobTitle: string, salary: number) {
// ๐ MUST call parent constructor first!
super(name, age); // This initializes name, age, and id
// โจ Now we can add our own properties
this.jobTitle = jobTitle;
this.salary = salary;
console.log(`๐จโ๐ผ Employee specialized: ${jobTitle}`);
}
// ๐ผ Employee-specific method
work(): string {
return `${this.name} is working as a ${this.jobTitle}! ๐ผ`;
}
// ๐ Get complete employee info
getInfo(): string {
// ๐ Call parent's getInfo, then add our own details
const parentInfo = super.getInfo(); // Gets basic person info
return `${parentInfo} - ${this.jobTitle} ($${this.salary.toLocaleString()})`;
}
}
// ๐ฎ Let's see it in action!
const employee = new Employee("Alice", 30, "Senior Developer", 95000);
console.log(employee.greet()); // "Hello, I'm Alice! ๐" (inherited)
console.log(employee.work()); // "Alice is working as a Senior Developer! ๐ผ"
console.log(employee.getInfo()); // Combined parent + child info
๐ก Explanation: Notice how super(name, age)
in the constructor calls the parent constructor, and super.getInfo()
calls the parent method!
๐ฏ Method Enhancement Pattern
Hereโs how to enhance parent functionality without losing it:
// ๐ฆ Bank account base class
class BankAccount {
protected balance: number;
protected accountNumber: string;
constructor(accountNumber: string, initialBalance: number = 0) {
this.accountNumber = accountNumber;
this.balance = initialBalance;
console.log(`๐ฆ Account ${accountNumber} created with $${initialBalance}`);
}
// ๐ฐ Basic deposit
deposit(amount: number): void {
if (amount > 0) {
this.balance += amount;
console.log(`โ
Deposited $${amount}. New balance: $${this.balance}`);
} else {
console.log("โ Deposit amount must be positive");
}
}
// ๐ธ Basic withdrawal
withdraw(amount: number): boolean {
if (amount > 0 && amount <= this.balance) {
this.balance -= amount;
console.log(`โ
Withdrew $${amount}. New balance: $${this.balance}`);
return true;
} else {
console.log("โ Invalid withdrawal amount");
return false;
}
}
// ๐ Check balance
getBalance(): number {
return this.balance;
}
}
// ๐ณ Premium account with enhanced features
class PremiumAccount extends BankAccount {
private rewardPoints: number = 0;
private bonusRate: number = 0.02; // 2% bonus
constructor(accountNumber: string, initialBalance: number = 0) {
super(accountNumber, initialBalance); // ๐ Call parent constructor
console.log("โจ Premium features activated!");
}
// ๐ Enhanced deposit with rewards
deposit(amount: number): void {
// ๐ First, do the normal deposit
super.deposit(amount);
// โจ Then add premium features
if (amount > 0) {
const bonusPoints = Math.floor(amount * this.bonusRate);
this.rewardPoints += bonusPoints;
console.log(`๐ Earned ${bonusPoints} reward points! Total: ${this.rewardPoints}`);
}
}
// ๐ Enhanced withdrawal with premium benefits
withdraw(amount: number): boolean {
// ๐ Try the normal withdrawal first
const success = super.withdraw(amount);
// โจ Add premium features if successful
if (success && amount >= 100) {
console.log("๐ Large withdrawal bonus: +5 reward points!");
this.rewardPoints += 5;
}
return success;
}
// ๐ Premium-specific method
getRewardPoints(): number {
return this.rewardPoints;
}
// ๐ฏ Redeem points for cash
redeemPoints(): void {
if (this.rewardPoints >= 100) {
const cashValue = Math.floor(this.rewardPoints / 100) * 10; // $10 per 100 points
this.rewardPoints %= 100; // Keep remainder
// ๐ Use parent's deposit method to add the cash
super.deposit(cashValue);
console.log(`๐ Redeemed points for $${cashValue}!`);
} else {
console.log("โ Need at least 100 points to redeem");
}
}
}
// ๐ณ Let's test premium features!
const premiumAccount = new PremiumAccount("PREM001", 1000);
premiumAccount.deposit(500); // Earns reward points!
premiumAccount.withdraw(200); // Earns bonus points!
console.log(`๐ฐ Balance: $${premiumAccount.getBalance()}`);
console.log(`๐ Reward Points: ${premiumAccount.getRewardPoints()}`);
๐ก Practical Examples
๐ฎ Example 1: Game Character Evolution
Letโs create a game where characters can evolve and gain new abilities:
// ๐ก๏ธ Base warrior class
class Warrior {
name: string;
health: number;
strength: number;
level: number;
constructor(name: string) {
this.name = name;
this.health = 100;
this.strength = 15;
this.level = 1;
console.log(`โ๏ธ ${name} becomes a warrior!`);
}
// โ๏ธ Basic attack
attack(): number {
const damage = this.strength + Math.floor(Math.random() * 10);
console.log(`โ๏ธ ${this.name} attacks for ${damage} damage!`);
return damage;
}
// ๐ก๏ธ Defend action
defend(): void {
console.log(`๐ก๏ธ ${this.name} raises their shield!`);
}
// ๐ Level up
levelUp(): void {
this.level++;
this.health += 20;
this.strength += 3;
console.log(`๐ ${this.name} reached level ${this.level}!`);
}
// ๐ Get stats
getStats(): string {
return `โ๏ธ ${this.name} - Level ${this.level} | HP: ${this.health} | STR: ${this.strength}`;
}
}
// ๐ฐ Paladin - evolved warrior with holy powers
class Paladin extends Warrior {
holyPower: number;
healingAbility: number;
constructor(name: string) {
// ๐ First become a warrior
super(name);
// โจ Then gain holy powers
this.holyPower = 25;
this.healingAbility = 15;
console.log(`โจ ${name} is blessed with holy power!`);
}
// ๐ Enhanced attack with holy damage
attack(): number {
// ๐ Do the basic warrior attack
const basicDamage = super.attack();
// โจ Add holy damage
const holyDamage = Math.floor(this.holyPower / 5);
const totalDamage = basicDamage + holyDamage;
if (holyDamage > 0) {
console.log(`โจ Holy power adds ${holyDamage} divine damage!`);
}
return totalDamage;
}
// ๐ก๏ธ Enhanced defend with blessing
defend(): void {
// ๐ Do basic defense
super.defend();
// โจ Add divine blessing
console.log(`โจ Divine blessing protects ${this.name}!`);
this.heal(5); // Self-heal while defending
}
// ๐ Healing ability
heal(amount: number): void {
this.health = Math.min(this.health + amount, 100 + (this.level * 20));
console.log(`๐ ${this.name} heals for ${amount} HP! Current: ${this.health}`);
}
// ๐ Enhanced level up with holy power growth
levelUp(): void {
// ๐ Do the basic level up
super.levelUp();
// โจ Grow holy powers
this.holyPower += 5;
this.healingAbility += 3;
console.log(`โจ Holy powers grow stronger! Holy Power: ${this.holyPower}`);
}
// ๐ Prayer for team healing
prayForTeam(): void {
console.log(`๐ ${this.name} prays for divine intervention!`);
console.log("โจ Team receives blessing of protection!");
}
// ๐ Enhanced stats with holy info
getStats(): string {
// ๐ Get basic warrior stats
const basicStats = super.getStats();
// โจ Add paladin-specific info
return `${basicStats} | Holy: ${this.holyPower} | Heal: ${this.healingAbility} โจ`;
}
}
// โก Thunder Knight - ultimate evolution
class ThunderKnight extends Paladin {
lightningPower: number;
stormsInvoked: number;
constructor(name: string) {
// ๐ First become a paladin (which calls warrior constructor too!)
super(name);
// โก Gain storm powers
this.lightningPower = 40;
this.stormsInvoked = 0;
console.log(`โก ${name} commands the power of storms!`);
}
// โก Ultimate attack with all powers combined
attack(): number {
// ๐ Get paladin attack (which includes warrior attack + holy damage)
const combinedDamage = super.attack();
// โก Add lightning damage
const lightningDamage = Math.floor(this.lightningPower / 3);
const finalDamage = combinedDamage + lightningDamage;
console.log(`โก Lightning strikes for ${lightningDamage} shock damage!`);
return finalDamage;
}
// ๐ฉ๏ธ Special storm ability
invokeStorm(): void {
this.stormsInvoked++;
console.log(`๐ฉ๏ธ ${this.name} summons a devastating storm! (Storm #${this.stormsInvoked})`);
// โก Massive damage attack
const stormDamage = this.lightningPower * 2;
console.log(`โก Storm deals ${stormDamage} area damage!`);
// ๐ Use parent's heal to recover from the effort
this.heal(10);
}
// ๐ Triple-enhanced level up
levelUp(): void {
// ๐ Do paladin level up (which does warrior level up too!)
super.levelUp();
// โก Grow storm powers
this.lightningPower += 8;
console.log(`โก Storm powers intensify! Lightning Power: ${this.lightningPower}`);
}
// ๐ Ultimate stats display
getStats(): string {
// ๐ Get paladin stats (which includes warrior stats)
const inheritedStats = super.getStats();
// โก Add thunder knight info
return `${inheritedStats} | Lightning: ${this.lightningPower} | Storms: ${this.stormsInvoked} โก`;
}
}
// ๐ฎ Let's witness the evolution!
const hero = new ThunderKnight("Thorgar");
console.log("\n" + hero.getStats());
hero.attack(); // Combines all three attack types!
hero.defend(); // Enhanced defense with healing
hero.invokeStorm(); // Unique storm ability
hero.levelUp(); // Triple-enhanced leveling
console.log("\n" + hero.getStats());
๐ช Example 2: E-commerce Notification System
Letโs build a notification system that builds upon base functionality:
// ๐จ Base notification class
class Notification {
id: string;
message: string;
timestamp: Date;
priority: 'low' | 'medium' | 'high';
sent: boolean = false;
constructor(message: string, priority: 'low' | 'medium' | 'high' = 'medium') {
this.id = `notif_${Date.now()}_${Math.random().toString(36).substr(2, 5)}`;
this.message = message;
this.priority = priority;
this.timestamp = new Date();
console.log(`๐จ Notification created: ${this.id}`);
}
// ๐ค Basic send method
send(): boolean {
if (this.sent) {
console.log("โ ๏ธ Notification already sent");
return false;
}
this.sent = true;
console.log(`๐ค Notification sent: "${this.message}"`);
return true;
}
// ๐ Get notification details
getDetails(): string {
return `๐จ ${this.id} | ${this.priority.toUpperCase()} | ${this.message} | ${this.timestamp.toLocaleTimeString()}`;
}
// ๐ฏ Get priority emoji
getPriorityEmoji(): string {
const emojis = { low: '๐ข', medium: '๐ก', high: '๐ด' };
return emojis[this.priority];
}
}
// ๐ง Email notification with enhanced features
class EmailNotification extends Notification {
recipient: string;
subject: string;
attachments: string[];
constructor(recipient: string, subject: string, message: string, priority: 'low' | 'medium' | 'high' = 'medium') {
// ๐ Create base notification
super(message, priority);
// โจ Add email-specific properties
this.recipient = recipient;
this.subject = subject;
this.attachments = [];
console.log(`๐ง Email notification prepared for ${recipient}`);
}
// ๐ Add attachment
addAttachment(filePath: string): void {
this.attachments.push(filePath);
console.log(`๐ Attached: ${filePath}`);
}
// ๐ Enhanced send with email-specific logic
send(): boolean {
// ๐ Check if base send is successful
if (!super.send()) {
return false; // Already sent or failed
}
// โจ Email-specific sending logic
console.log(`๐ง Sending email to: ${this.recipient}`);
console.log(`๐ Subject: ${this.subject}`);
if (this.attachments.length > 0) {
console.log(`๐ Attachments: ${this.attachments.join(', ')}`);
}
// ๐ฏ Priority-based delivery
if (this.priority === 'high') {
console.log('๐จ HIGH PRIORITY: Sending via express delivery!');
}
console.log('โ
Email delivered successfully!');
return true;
}
// ๐ Enhanced details with email info
getDetails(): string {
// ๐ Get base details
const baseDetails = super.getDetails();
// โจ Add email-specific details
const emailInfo = `๐ง To: ${this.recipient} | Subject: "${this.subject}"`;
const attachmentInfo = this.attachments.length > 0
? ` | ๐ ${this.attachments.length} attachments`
: '';
return `${baseDetails} | ${emailInfo}${attachmentInfo}`;
}
}
// ๐ฑ SMS notification with character limits
class SMSNotification extends Notification {
phoneNumber: string;
maxLength: number = 160;
constructor(phoneNumber: string, message: string, priority: 'low' | 'medium' | 'high' = 'medium') {
// ๐ Create base notification with truncated message if needed
const truncatedMessage = message.length > 160
? message.substring(0, 157) + '...'
: message;
super(truncatedMessage, priority);
// โจ Add SMS-specific properties
this.phoneNumber = phoneNumber;
console.log(`๐ฑ SMS notification prepared for ${phoneNumber}`);
if (message.length > 160) {
console.log(`โ ๏ธ Message truncated from ${message.length} to ${this.message.length} characters`);
}
}
// ๐ Enhanced send with SMS-specific features
send(): boolean {
// ๐ Do the basic notification send
if (!super.send()) {
return false;
}
// โจ SMS-specific logic
console.log(`๐ฑ Sending SMS to: ${this.phoneNumber}`);
console.log(`๐ Message (${this.message.length}/${this.maxLength} chars): "${this.message}"`);
// ๐ฏ Priority affects delivery speed
const deliveryTime = this.priority === 'high' ? 'immediate' : 'within 1 minute';
console.log(`โฑ๏ธ Delivery time: ${deliveryTime}`);
console.log('โ
SMS sent successfully!');
return true;
}
// ๐ Enhanced details with SMS info
getDetails(): string {
// ๐ Get base details
const baseDetails = super.getDetails();
// โจ Add SMS-specific details
const smsInfo = `๐ฑ To: ${this.phoneNumber} | Length: ${this.message.length}/${this.maxLength}`;
return `${baseDetails} | ${smsInfo}`;
}
}
// ๐ Push notification for mobile apps
class PushNotification extends Notification {
deviceToken: string;
appName: string;
soundEnabled: boolean;
badgeCount: number;
constructor(deviceToken: string, appName: string, message: string, priority: 'low' | 'medium' | 'high' = 'medium') {
// ๐ Create base notification
super(message, priority);
// โจ Add push-specific properties
this.deviceToken = deviceToken;
this.appName = appName;
this.soundEnabled = priority !== 'low'; // Low priority = silent
this.badgeCount = 1;
console.log(`๐ Push notification prepared for ${appName}`);
}
// ๐ Toggle sound
toggleSound(): void {
this.soundEnabled = !this.soundEnabled;
console.log(`๐ Sound ${this.soundEnabled ? 'enabled' : 'disabled'}`);
}
// ๐ Enhanced send with push-specific features
send(): boolean {
// ๐ Do the basic send
if (!super.send()) {
return false;
}
// โจ Push notification specific logic
console.log(`๐ Sending push notification to ${this.appName}`);
console.log(`๐ฑ Device: ${this.deviceToken.substring(0, 8)}...`);
console.log(`๐ Message: "${this.message}"`);
if (this.soundEnabled) {
console.log(`๐ Playing notification sound`);
} else {
console.log(`๐ Silent notification`);
}
console.log(`๐ข Badge count: ${this.badgeCount}`);
console.log('โ
Push notification delivered!');
return true;
}
// ๐ Enhanced details with push info
getDetails(): string {
// ๐ Get base details
const baseDetails = super.getDetails();
// โจ Add push-specific details
const pushInfo = `๐ App: ${this.appName} | Sound: ${this.soundEnabled ? '๐' : '๐'} | Badge: ${this.badgeCount}`;
return `${baseDetails} | ${pushInfo}`;
}
}
// ๐ฌ Notification manager to handle all types
class NotificationManager {
private notifications: Notification[] = [];
addNotification(notification: Notification): void {
this.notifications.push(notification);
console.log(`โ Added notification: ${notification.id}`);
}
sendAll(): void {
console.log(`๐ค Sending ${this.notifications.length} notifications...`);
this.notifications.forEach(notification => {
notification.send();
});
}
showAllDetails(): void {
console.log('\n๐ All Notifications:');
this.notifications.forEach((notification, index) => {
console.log(`${index + 1}. ${notification.getDetails()}`);
});
}
}
// ๐ฎ Let's test our notification system!
const notificationManager = new NotificationManager();
// Create different types of notifications
const email = new EmailNotification(
'[email protected]',
'Welcome to TypeScript!',
'Thanks for joining our TypeScript tutorial series!',
'high'
);
email.addAttachment('welcome-guide.pdf');
const sms = new SMSNotification(
'+1234567890',
'Your TypeScript tutorial is ready! Click here to start learning: https://example.com/ts-tutorial-super-keyword',
'medium'
);
const push = new PushNotification(
'device_token_abc123xyz',
'TypeScript Academy',
'New lesson available: Super Keyword!',
'high'
);
// Add to manager and send
notificationManager.addNotification(email);
notificationManager.addNotification(sms);
notificationManager.addNotification(push);
notificationManager.showAllDetails();
console.log('\n๐ Sending all notifications...\n');
notificationManager.sendAll();
๐ Advanced Concepts
๐งโโ๏ธ Advanced Topic 1: Super with Static Methods
You can also use super
with static methods:
// ๐ญ Base factory class
class VehicleFactory {
static vehicleCount: number = 0;
static createVehicle(): string {
this.vehicleCount++;
return `๐ Vehicle #${this.vehicleCount} created`;
}
static getReport(): string {
return `๐ Total vehicles created: ${this.vehicleCount}`;
}
}
// โ๏ธ Specialized aircraft factory
class AircraftFactory extends VehicleFactory {
static aircraftCount: number = 0;
// ๐ Enhanced creation with aircraft specifics
static createVehicle(): string {
// ๐ Call parent's method first
const baseResult = super.createVehicle();
// โจ Add aircraft-specific logic
this.aircraftCount++;
return `${baseResult} โ๏ธ (Aircraft #${this.aircraftCount})`;
}
// ๐ Enhanced report with aircraft details
static getReport(): string {
// ๐ Get base report
const baseReport = super.getReport();
// โจ Add aircraft details
return `${baseReport} | Aircraft: ${this.aircraftCount} โ๏ธ`;
}
}
console.log(AircraftFactory.createVehicle()); // Creates both vehicle and aircraft
console.log(AircraftFactory.createVehicle());
console.log(AircraftFactory.getReport()); // Shows both counts
๐๏ธ Advanced Topic 2: Super in Method Chaining
Using super
with method chaining patterns:
// ๐ Chainable configuration class
class ConfigBuilder {
protected config: Record<string, any> = {};
setValue(key: string, value: any): this {
this.config[key] = value;
console.log(`โ๏ธ Set ${key} = ${value}`);
return this;
}
build(): Record<string, any> {
console.log('๐๏ธ Configuration built!');
return { ...this.config };
}
}
// ๐๏ธ Database configuration builder
class DatabaseConfigBuilder extends ConfigBuilder {
// ๐ Enhanced setValue with validation
setValue(key: string, value: any): this {
// ๐ก๏ธ Add database-specific validation
if (key === 'port' && (typeof value !== 'number' || value < 1 || value > 65535)) {
console.log('โ Invalid port number');
return this;
}
if (key === 'host' && typeof value !== 'string') {
console.log('โ Host must be a string');
return this;
}
// ๐ Call parent's setValue if validation passes
return super.setValue(key, value);
}
// ๐๏ธ Database-specific methods
setConnectionPool(size: number): this {
return this.setValue('connectionPoolSize', size);
}
setSSL(enabled: boolean): this {
return this.setValue('ssl', enabled);
}
// ๐ Enhanced build with database defaults
build(): Record<string, any> {
// Set defaults before building
if (!this.config.port) this.setValue('port', 5432);
if (!this.config.host) this.setValue('host', 'localhost');
// ๐ Call parent's build
return super.build();
}
}
// ๐ Method chaining in action!
const dbConfig = new DatabaseConfigBuilder()
.setValue('database', 'typescript_tutorial')
.setValue('username', 'dev_user')
.setValue('port', 5432)
.setConnectionPool(10)
.setSSL(true)
.build();
console.log('๐ Final config:', dbConfig);
โ ๏ธ Common Pitfalls and Solutions
๐ฑ Pitfall 1: Forgetting to Call super() in Constructor
// โ Wrong way - missing super() call!
class BadChild extends Person {
specialty: string;
constructor(name: string, age: number, specialty: string) {
// Missing super(name, age) - TypeScript will error!
this.specialty = specialty; // ๐ฅ Error: must call super() first
}
}
// โ
Correct way - always call super() first!
class GoodChild extends Person {
specialty: string;
constructor(name: string, age: number, specialty: string) {
super(name, age); // โ
Call parent constructor first!
this.specialty = specialty; // โ
Now this works
}
}
๐คฏ Pitfall 2: Using โthisโ Before super()
class Parent {
value: number;
constructor(value: number) {
this.value = value;
}
}
// โ Wrong way - using 'this' before super()!
class BadChild extends Parent {
multiplier: number;
constructor(value: number, multiplier: number) {
this.multiplier = multiplier; // ๐ฅ Error: must call super() before using 'this'
super(value);
}
}
// โ
Correct way - super() first, then 'this'!
class GoodChild extends Parent {
multiplier: number;
constructor(value: number, multiplier: number) {
super(value); // โ
Call super() first
this.multiplier = multiplier; // โ
Now 'this' is available
}
}
๐ Pitfall 3: Infinite Recursion with super
class Parent {
calculate(): number {
return 42;
}
}
// โ Dangerous - potential infinite loop!
class BadChild extends Parent {
calculate(): number {
// This calls the parent method correctly
const parentResult = super.calculate();
// But this would call itself infinitely!
// return this.calculate() + parentResult; // ๐ฅ Stack overflow!
return parentResult * 2; // โ
This is correct
}
}
๐ ๏ธ Best Practices
- ๐ Always Call super() First: In constructors, call
super()
before usingthis
- ๐ฏ Use super for Enhancement: Donโt replace parent functionality, enhance it
- ๐ Be Explicit: Use
super.method()
to make parent calls obvious - โก Call Once: Donโt call the same super method multiple times unnecessarily
- ๐ Document Intent: Comment why youโre calling super methods
๐งช Hands-On Exercise
๐ฏ Challenge: Build a Social Media Post System
Create a social media system where different post types enhance base functionality:
๐ Requirements:
- โ
Base
Post
class with content, author, timestamp, likes - ๐ธ
PhotoPost
class with image handling and filters - ๐น
VideoPost
class with duration and quality settings - ๐
TextPost
class with character limits and hashtag extraction - ๐ Each class should enhance parent methods using
super
๐ Bonus Points:
- Add comment system to all post types
- Implement engagement scoring
- Create post analytics features
๐ก Solution
๐ Click to see solution
// ๐ฑ Base social media post
class Post {
id: string;
content: string;
author: string;
timestamp: Date;
likes: number = 0;
comments: string[] = [];
constructor(content: string, author: string) {
this.id = `post_${Date.now()}_${Math.random().toString(36).substr(2, 5)}`;
this.content = content;
this.author = author;
this.timestamp = new Date();
console.log(`๐ฑ Post created by ${author}`);
}
// ๐ Like the post
like(): void {
this.likes++;
console.log(`๐ Post liked! Total likes: ${this.likes}`);
}
// ๐ฌ Add comment
addComment(comment: string): void {
this.comments.push(comment);
console.log(`๐ฌ Comment added: "${comment}"`);
}
// ๐ Get engagement score
getEngagementScore(): number {
return this.likes + (this.comments.length * 2);
}
// ๐ Share the post
share(): void {
console.log(`๐ "${this.content.substring(0, 30)}..." shared by ${this.author}`);
}
// ๐ Get post summary
getSummary(): string {
return `๐ฑ ${this.author} | ${this.timestamp.toLocaleDateString()} | ๐ ${this.likes} | ๐ฌ ${this.comments.length}`;
}
}
// ๐ธ Photo post with image features
class PhotoPost extends Post {
imageUrl: string;
filter: string;
altText: string;
constructor(content: string, author: string, imageUrl: string, altText: string = '') {
// ๐ Create base post
super(content, author);
// โจ Add photo-specific properties
this.imageUrl = imageUrl;
this.filter = 'none';
this.altText = altText;
console.log(`๐ธ Photo attached: ${imageUrl}`);
}
// ๐จ Apply filter
applyFilter(filter: string): void {
this.filter = filter;
console.log(`๐จ Applied ${filter} filter to photo`);
}
// ๐ Enhanced like with photo engagement
like(): void {
// ๐ Do the basic like
super.like();
// โจ Photo posts get bonus engagement
if (this.likes % 10 === 0) {
console.log(`๐ธ Photo milestone! ${this.likes} likes reached!`);
}
}
// ๐ Enhanced share with image preview
share(): void {
// ๐ Do basic share
super.share();
// โจ Add photo-specific sharing
console.log(`๐ผ๏ธ Shared with image preview: ${this.imageUrl}`);
}
// ๐ Enhanced summary with photo info
getSummary(): string {
// ๐ Get base summary
const baseSummary = super.getSummary();
// โจ Add photo details
return `${baseSummary} | ๐ธ Photo (${this.filter} filter)`;
}
}
// ๐น Video post with media features
class VideoPost extends Post {
videoUrl: string;
duration: number; // in seconds
quality: '480p' | '720p' | '1080p' | '4K';
views: number = 0;
constructor(content: string, author: string, videoUrl: string, duration: number, quality: '480p' | '720p' | '1080p' | '4K' = '720p') {
// ๐ Create base post
super(content, author);
// โจ Add video-specific properties
this.videoUrl = videoUrl;
this.duration = duration;
this.quality = quality;
console.log(`๐น Video attached: ${this.getFormattedDuration()} at ${quality}`);
}
// โฏ๏ธ Play video
play(): void {
this.views++;
console.log(`โถ๏ธ Playing video... Views: ${this.views}`);
}
// ๐ Get formatted duration
getFormattedDuration(): string {
const minutes = Math.floor(this.duration / 60);
const seconds = this.duration % 60;
return `${minutes}:${seconds.toString().padStart(2, '0')}`;
}
// ๐ Enhanced engagement score including views
getEngagementScore(): number {
// ๐ Get base engagement
const baseEngagement = super.getEngagementScore();
// โจ Add view-based engagement
const viewEngagement = Math.floor(this.views / 10);
return baseEngagement + viewEngagement;
}
// ๐ Enhanced share with video preview
share(): void {
// ๐ Do basic share
super.share();
// โจ Add video-specific sharing
console.log(`๐ฌ Shared video: ${this.getFormattedDuration()} at ${this.quality}`);
}
// ๐ Enhanced summary with video info
getSummary(): string {
// ๐ Get base summary
const baseSummary = super.getSummary();
// โจ Add video details
return `${baseSummary} | ๐น ${this.getFormattedDuration()} (${this.views} views)`;
}
}
// ๐ Text post with text processing features
class TextPost extends Post {
hashtags: string[] = [];
mentions: string[] = [];
characterLimit: number = 280;
constructor(content: string, author: string) {
// ๐ Process content before creating post
const processedContent = content.length > 280
? content.substring(0, 277) + '...'
: content;
// ๐ Create base post with processed content
super(processedContent, author);
// โจ Extract hashtags and mentions
this.extractHashtags();
this.extractMentions();
if (content.length > 280) {
console.log(`โ๏ธ Text truncated from ${content.length} to ${this.content.length} characters`);
}
}
// ๐ Extract hashtags from content
private extractHashtags(): void {
const hashtagRegex = /#(\w+)/g;
let match;
while ((match = hashtagRegex.exec(this.content)) !== null) {
this.hashtags.push(match[1]);
}
if (this.hashtags.length > 0) {
console.log(`๐ท๏ธ Found hashtags: ${this.hashtags.join(', ')}`);
}
}
// ๐ฅ Extract mentions from content
private extractMentions(): void {
const mentionRegex = /@(\w+)/g;
let match;
while ((match = mentionRegex.exec(this.content)) !== null) {
this.mentions.push(match[1]);
}
if (this.mentions.length > 0) {
console.log(`๐ฅ Mentioned users: ${this.mentions.join(', ')}`);
}
}
// ๐ Enhanced share with hashtag promotion
share(): void {
// ๐ Do basic share
super.share();
// โจ Promote hashtags when sharing
if (this.hashtags.length > 0) {
console.log(`๐ท๏ธ Trending hashtags: ${this.hashtags.map(tag => `#${tag}`).join(' ')}`);
}
}
// ๐ Enhanced summary with text features
getSummary(): string {
// ๐ Get base summary
const baseSummary = super.getSummary();
// โจ Add text-specific details
const textInfo = `๐ ${this.content.length}/${this.characterLimit} chars`;
const hashtagInfo = this.hashtags.length > 0 ? ` | ๐ท๏ธ ${this.hashtags.length}` : '';
const mentionInfo = this.mentions.length > 0 ? ` | ๐ฅ ${this.mentions.length}` : '';
return `${baseSummary} | ${textInfo}${hashtagInfo}${mentionInfo}`;
}
}
// ๐ฑ Social media feed manager
class SocialFeed {
private posts: Post[] = [];
addPost(post: Post): void {
this.posts.push(post);
console.log(`โ Added post to feed: ${post.id}`);
}
showFeed(): void {
console.log('\n๐ฑ Social Media Feed:');
this.posts.forEach((post, index) => {
console.log(`${index + 1}. ${post.getSummary()}`);
});
}
getTopPosts(count: number = 3): Post[] {
return this.posts
.sort((a, b) => b.getEngagementScore() - a.getEngagementScore())
.slice(0, count);
}
getTrendingHashtags(): string[] {
const hashtagCount = new Map<string, number>();
this.posts.forEach(post => {
if (post instanceof TextPost) {
post.hashtags.forEach(hashtag => {
hashtagCount.set(hashtag, (hashtagCount.get(hashtag) || 0) + 1);
});
}
});
return Array.from(hashtagCount.entries())
.sort(([,a], [,b]) => b - a)
.slice(0, 5)
.map(([hashtag]) => `#${hashtag}`);
}
}
// ๐ฎ Let's create some social media magic!
const feed = new SocialFeed();
// Create different types of posts
const textPost = new TextPost(
'Just learned about the super keyword in #TypeScript! Amazing how it connects parent and child classes. Thanks @typescript @developer #coding #learning',
'CodeLearner'
);
const photoPost = new PhotoPost(
'Beautiful sunset from my coding session! ๐
',
'DevPhotographer',
'https://example.com/sunset.jpg',
'Golden sunset over mountains with laptop in foreground'
);
const videoPost = new VideoPost(
'TypeScript tutorial: Super keyword explained!',
'TechTeacher',
'https://example.com/tutorial.mp4',
450, // 7:30 minutes
'1080p'
);
// Add some engagement
textPost.like();
textPost.addComment('Great explanation!');
textPost.addComment('Thanks for sharing!');
photoPost.like();
photoPost.like();
photoPost.applyFilter('vintage');
videoPost.play();
videoPost.play();
videoPost.play();
videoPost.like();
// Add to feed
feed.addPost(textPost);
feed.addPost(photoPost);
feed.addPost(videoPost);
// Show results
feed.showFeed();
console.log('\n๐ Top Posts:');
feed.getTopPosts().forEach((post, index) => {
console.log(`${index + 1}. ${post.getSummary()} (Score: ${post.getEngagementScore()})`);
});
console.log('\n๐ฅ Trending Hashtags:');
console.log(feed.getTrendingHashtags().join(' '));
// Share some posts
console.log('\n๐ Sharing posts...');
textPost.share();
photoPost.share();
videoPost.share();
๐ Key Takeaways
Youโve mastered the super keyword! Hereโs what you can now do:
- โ Call parent constructors with super() ๐
- โ Access parent methods effectively ๐ง
- โ Enhance functionality without losing parent features ๐
- โ Build proper class hierarchies with clear communication ๐๏ธ
- โ Avoid common super pitfalls like a pro ๐ก๏ธ
Remember: super
is your bridge to parent classes - use it to enhance, not replace! ๐
๐ค Next Steps
Congratulations! ๐ Youโve mastered the super keyword!
Hereโs what to do next:
- ๐ป Practice with the social media system exercise above
- ๐๏ธ Build your own class hierarchy using super effectively
- ๐ Move on to our next tutorial: Method Overriding: Customizing Inherited Behavior
- ๐ Experiment with static super calls and advanced patterns!
Remember: Every great class hierarchy uses super effectively. Keep building, keep learning, and super-charge your TypeScript skills! ๐
Happy coding! ๐๐โจ