Difficulty: Beginner
Why would you choose TypeScript over JavaScript? What problems does TypeScript solve?
TypeScript is a statically typed superset of JavaScript that compiles to plain JS. It solves several major pain points in JavaScript development:
1. Catches bugs at compile time instead of runtime - typos, wrong argument types, missing properties are all caught before your code ever runs.
2. Self-documenting code - type annotations serve as living documentation. Function signatures tell you exactly what inputs are expected and what output is returned.
3. Superior IDE support - autocompletion, refactoring, go-to-definition, and inline errors are dramatically better with types.
4. Safer refactoring - when you change a type or interface, the compiler immediately shows every place that needs updating.
5. Gradual adoption - since TS is a superset of JS, you can adopt it incrementally. Any valid JS is valid TS.
// JavaScript - these bugs only show up at runtime
function getUser(id) {
return fetch('/api/users/' + id);
}
getUser(); // No error in JS, but fails at runtime!
// TypeScript - caught immediately
function getUser(id: number): Promise<User> {
return fetch('/api/users/' + id).then(r => r.json());
}
getUser(); // Error: Expected 1 argument, got 0
getUser('abc'); // Error: Argument of type 'string' not assignable to 'number'
getUser(123); // OK
// Property access safety
interface User {
name: string;
email: string;
}
const user: User = { name: 'Alice', email: 'a@b.com' };
console.log(user.nme); // Error: Property 'nme' does not exist. Did you mean 'name'?
TypeScript catches entire categories of bugs that JavaScript would only reveal at runtime, including typos, wrong types, and missing arguments.
// JavaScript - what does this function expect? Who knows.
function processOrder(order, options) {
// ... you'd have to read the implementation
}
// TypeScript - crystal clear contract
interface Order {
id: string;
items: { productId: string; quantity: number; price: number }[];
customerId: string;
status: 'pending' | 'confirmed' | 'shipped' | 'delivered';
}
interface ProcessOptions {
sendEmail?: boolean;
validateInventory?: boolean;
applyDiscount?: string;
}
function processOrder(order: Order, options: ProcessOptions = {}): Promise<Order> {
// The signature IS the documentation
}
// Callers know exactly what to pass
processOrder(
{ id: '1', items: [], customerId: 'c1', status: 'pending' },
{ sendEmail: true }
);
Type annotations serve as always-up-to-date documentation. Unlike JSDoc comments, types are enforced by the compiler and cannot become stale.
// Before: User has 'name' field
interface User {
id: number;
name: string;
email: string;
}
// After refactoring: split into firstName + lastName
interface User {
id: number;
firstName: string;
lastName: string;
email: string;
}
// TypeScript immediately flags EVERY place that used 'name'
// File: components/UserCard.tsx
// Error: Property 'name' does not exist on type 'User'
// File: utils/formatUser.ts
// Error: Property 'name' does not exist on type 'User'
// File: api/createUser.ts
// Error: 'name' does not exist in type 'User'
// In JavaScript, these would be silent bugs discovered by users
When you change a type, the compiler creates a checklist of every file that needs updating. This makes large refactors safe and complete.
TypeScript Benefits, Static Typing, JavaScript Comparison, Type Safety, Developer Experience