Skip to main content

Complete SMS Application in TypeScript

Level: Beginner

ℹ️ What You'll Learn
  • Modeling complete SMS domain: Student, Teacher, Exam, Fee types
  • API integration with typed responses
  • Form handling with type-safe inputs
  • State management patterns in TypeScript
  • Error handling with specific error types
  • Service layer with generic API client
  • Component communication with typed events
  • Complete student list and detail pages

Why This Matters

Complete SMS Application in TypeScript helps you write safer frontend code. In ASP.NET Core projects, TypeScript makes API response shapes, form models, DOM values, and reusable helpers easier to maintain.

Full working SMS dashboard with TypeScript.

The Problem

JavaScript allows many mistakes to appear only at runtime. This lesson shows how Complete SMS Application in TypeScript lets TypeScript catch wrong values, missing properties, and unsafe assumptions before the page reaches users.

Complete TypeScript Implementation

// Types and Interfaces
interface Student {
id: number;
rollNumber: string;
name: string;
email: string;
className: string;
status: 'Active' | 'Inactive' | 'Graduated';
}

interface ApiResponse<T> {
success: boolean;
data?: T;
error?: string;
}

// API Service Class
class StudentService {
private baseUrl = '/api/students';

async getAll(): Promise<ApiResponse<Student[]>> {
try {
const response = await fetch(this.baseUrl);
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const data = await response.json();
return { success: true, data };
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : 'Unknown error'
};
}
}

async create(student: Omit<Student, 'id'>): Promise<ApiResponse<Student>> {
try {
const response = await fetch(this.baseUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(student)
});

if (!response.ok) {
throw new Error('Creation failed');
}

const data = await response.json();
return { success: true, data };
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : 'Unknown error'
};
}
}

async delete(id: number): Promise<ApiResponse<void>> {
try {
const response = await fetch(`${this.baseUrl}/${id}`, {
method: 'DELETE'
});

if (!response.ok) {
throw new Error('Delete failed');
}

return { success: true };
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : 'Unknown error'
};
}
}
}

// UI Controller Class
class StudentDashboard {
private service: StudentService;
private form: HTMLFormElement;
private tableBody: HTMLTableSectionElement;
private countElement: HTMLSpanElement;
private errorDiv: HTMLDivElement;
private submitBtn: HTMLButtonElement;

constructor() {
this.service = new StudentService();
this.form = document.getElementById('studentForm') as HTMLFormElement;
this.tableBody = document.querySelector('tbody') as HTMLTableSectionElement;
this.countElement = document.getElementById('studentCount') as HTMLSpanElement;
this.errorDiv = document.getElementById('error') as HTMLDivElement;
this.submitBtn = this.form.querySelector('button[type="submit"]') as HTMLButtonElement;

this.initialize();
}

private initialize(): void {
this.loadStudents();
this.form.addEventListener('submit', (e) => this.handleSubmit(e));
document.addEventListener('click', (e) => this.handleTableClick(e));
}

private async loadStudents(): Promise<void> {
const result = await this.service.getAll();

if (!result.success) {
this.showError(result.error || 'Failed to load');
return;
}

this.tableBody.innerHTML = '';
const students = result.data || [];

students.forEach(student => {
const row = this.createTableRow(student);
this.tableBody.appendChild(row);
});

this.countElement.textContent = students.length.toString();
}

private createTableRow(student: Student): HTMLTableRowElement {
const row = document.createElement('tr');
row.dataset.studentId = student.id.toString();

const statusClass = student.status === 'Active' ? 'status-active' : 'status-inactive';

row.innerHTML = `
<td>${student.rollNumber}</td>
<td>${student.name}</td>
<td>${student.email}</td>
<td>${student.className}</td>
<td><span class="${statusClass}">${student.status}</span></td>
<td>
<button class="delete-btn" data-id="${student.id}">Delete</button>
</td>
`;

return row;
}

private handleSubmit(event: SubmitEvent): void {
event.preventDefault();

const formData = new FormData(this.form);
const studentData: Omit<Student, 'id'> = {
rollNumber: (formData.get('rollNumber') as string) || '',
name: (formData.get('name') as string) || '',
email: (formData.get('email') as string) || '',
className: (formData.get('className') as string) || '',
status: 'Active'
};

if (!studentData.name || !studentData.email) {
this.showError('Name and email required');
return;
}

this.registerStudent(studentData);
}

private async registerStudent(student: Omit<Student, 'id'>): Promise<void> {
this.submitBtn.disabled = true;
this.submitBtn.textContent = 'Registering...';

const result = await this.service.create(student);

if (!result.success) {
this.showError(result.error || 'Registration failed');
} else {
this.showSuccess(`${result.data?.name} registered!`);
this.form.reset();
this.loadStudents();
}

this.submitBtn.disabled = false;
this.submitBtn.textContent = 'Register';
}

private handleTableClick(event: MouseEvent): void {
const target = event.target as HTMLElement;

if (target.classList.contains('delete-btn')) {
const studentId = parseInt(target.dataset.id || '0');
const row = target.closest('tr') as HTMLTableRowElement;
const name = row.querySelector('td:nth-child(2)')?.textContent || 'Student';

if (confirm(`Delete ${name}?`)) {
this.deleteStudent(studentId);
}
}
}

private async deleteStudent(id: number): Promise<void> {
const result = await this.service.delete(id);

if (!result.success) {
this.showError(result.error || 'Delete failed');
} else {
this.showSuccess('Student deleted');
this.loadStudents();
}
}

private showError(message: string): void {
this.errorDiv.style.display = 'block';
this.errorDiv.textContent = `Error: ${message}`;
}

private showSuccess(message: string): void {
alert(message); // Or show in UI element
}
}

// Initialize on page load
document.addEventListener('DOMContentLoaded', () => {
new StudentDashboard();
});

HTML Structure

<!DOCTYPE html>
<html>
<head>
<title>SMS - TypeScript</title>
<style>
/* CSS from previous articles */
</style>
</head>
<body>

<div class="container">
<h1>Student Management System</h1>

<div id="error" style="display:none; color:red;"></div>

<!-- Registration Form -->
<form id="studentForm">
<label>Roll Number: <input type="text" name="rollNumber" required></label>
<label>Name: <input type="text" name="name" required></label>
<label>Email: <input type="email" name="email" required></label>
<label>Class: <select name="className" required>
<option value="">Select</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
</select></label>
<button type="submit">Register</button>
</form>

<!-- Student Table -->
<h2>Students (Total: <span id="studentCount">0</span>)</h2>
<table>
<thead>
<tr>
<th>Roll</th>
<th>Name</th>
<th>Email</th>
<th>Class</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>

<script src="app.ts"></script>

</body>
</html>

TypeScript Features Demonstrated

  • Interfaces — Student, ApiResponse types
  • Classes — StudentService, StudentDashboard
  • Type Safety — All parameters typed
  • GenericsApiResponse<T> for any data type
  • DOM Types — HTMLFormElement, HTMLTableSectionElement
  • Error Handling — Try/catch with typed responses
  • Discriminated Unions — Success/error responses
  • Access Modifiers — private methods and properties

Key Patterns

  1. Service Layer — API calls separated
  2. Controller Layer — UI logic separated
  3. Type-Safe — Every variable and function typed
  4. Error Handling — Responses indicate success/failure
  5. Event Delegation — Single listener for table
  6. Form Validation — Basic checks before submit

Ready for Angular

This structure mirrors Angular:

  • Classes with methods (Angular services)
  • Type safety throughout (Angular services)
  • Separation of concerns (Angular architecture)
  • Event handling (Angular templates)

Key Takeaways

  • TypeScript enables type-safe applications
  • Classes organize code effectively
  • Generics provide flexibility
  • Interfaces document contracts
  • Error handling is comprehensive
  • Architecture matches Angular patterns
💡 Backend Developer Tip

This TypeScript structure is similar to Angular service architecture. Moving to Angular will feel natural with this foundation.

⚠️ Production Checklist
  1. Add authentication
  2. Implement proper error logging
  3. Add loading states
  4. Validate on backend too
  5. Use environment variables for API URLs
  6. Handle network timeouts
  7. Add accessibility features
🤖Use AI to Learn Faster

Use ChatGPT, Claude, or Copilot to go deeper on Complete SMS TypeScript. Try these prompts:

  • "How does this compare to JavaScript version?"
  • "What would change in Angular?"
  • "How is this production-ready?"
  • "Quiz me on complete TypeScript"

💡 Tip: After reading this article, paste your own code into AI and ask "What could go wrong here and why?" — fastest way to find edge cases and deepen understanding.

Quick Definitions

  • Complete SMS Application in TypeScript - The main TypeScript concept explained in this lesson.
  • Type - A rule that describes what kind of value is allowed.
  • Interface - A contract that describes the shape of an object.
  • DTO model - The frontend shape of data coming from ASP.NET Core Web API.

Common Mistakes

  • Using any instead of defining a useful type
  • Making types too complex before understanding the data
  • Forgetting that API data still needs runtime validation
  • Confusing JavaScript runtime behavior with TypeScript compile-time checks
  • Not reusing shared types for repeated API models

Practice Task

Create a small TypeScript example using Complete SMS Application in TypeScript. Keep it connected to a School Management System scenario.

Suggested practice:

  1. Define a Student, Teacher, Attendance, or Marks model.
  2. Write one function or class using that type.
  3. Add one intentionally wrong value and read the TypeScript error.
  4. Fix the type or the data shape.
  5. Explain the type contract in your own words.

Quick Revision

QuestionAnswer
What is the main idea?Use TypeScript to make Complete SMS Application in TypeScript safer and clearer.
Where is it used?API models, forms, DOM code, helpers, and React/Next.js apps.
What should beginners avoid?Overusing any and ignoring API validation.
What is the best debugging habit?Read the TypeScript error and compare it with the expected data shape.
🎯 How would you explain Complete SMS Application in TypeScript in an interview?

Complete SMS Application in TypeScript is a TypeScript concept that improves JavaScript safety by making data shapes and function expectations clear. I would explain the problem it solves, show a small example, and mention how it helps with API-connected frontend code.

🎯 Where is this used in real projects?

It is used in API DTOs, form models, DOM access, helper functions, React props, service classes, and reusable frontend utilities.

Next Article

TypeScript overview ->

nexcoding.in