π― What is TypeScript?
TypeScript is a programming language developed by Microsoft that builds on JavaScript by adding static type definitions. It's often called a "superset" of JavaScript, meaning all valid JavaScript code is also valid TypeScript code.
The Relationship
TypeScript β JavaScript
TypeScript Code (.ts) β TypeScript Compiler (tsc) β JavaScript Code (.js)
βοΈ Side-by-Side Comparison
| Feature | JavaScript | TypeScript |
|---|---|---|
| Type System | Dynamic (types checked at runtime) | Static (types checked at compile time) |
| File Extension | .js | .ts (or .tsx for React) |
| Compilation | Runs directly in browser/Node.js | Must compile to JavaScript first |
| Error Detection | Errors found at runtime | Many errors caught during development |
| Learning Curve | Lower barrier to entry | Requires understanding types |
| IDE Support | Good | Excellent (better autocomplete) |
| Browser Support | Native support | Requires compilation step |
π Type Annotations
The most visible difference between TypeScript and JavaScript is type annotations. These tell TypeScript what type of value a variable, parameter, or return value should be.
Variable Types
JavaScript
// No type information
let name = "John";
let age = 30;
let isStudent = false;
let scores = [85, 90, 78];
// Can reassign to different types
name = 42; // No error!
TypeScript
// Explicit type annotations
let name: string = "John";
let age: number = 30;
let isStudent: boolean = false;
let scores: number[] = [85, 90, 78];
// Error: Type 'number' is not
// assignable to type 'string'
name = 42; // Compile error!
Function Types
JavaScript
// No parameter or return types
function add(a, b) {
return a + b;
}
// These all "work" but may not
// do what you expect
add(5, 3); // 8
add("5", "3"); // "53"
add(5); // NaN
TypeScript
// Parameter and return types
function add(a: number, b: number): number {
return a + b;
}
// Only valid calls compile
add(5, 3); // 8 β
add("5", "3"); // Error! β
add(5); // Error! β
π§ TypeScript-Only Features
Interfaces
Interfaces define the shape of an object, specifying what properties and methods it must have.
// Define an interface
interface Person {
name: string;
age: number;
email?: string; // Optional property (note the ?)
}
// Use the interface
function greet(person: Person): string {
return `Hello, ${person.name}!`;
}
// Valid - has required properties
let user1: Person = { name: "Alice", age: 25 };
// Valid - includes optional property
let user2: Person = { name: "Bob", age: 30, email: "bob@example.com" };
// Error - missing required property 'age'
let user3: Person = { name: "Charlie" }; // Compile error!
Type Aliases
Type aliases create custom names for types, making code more readable and reusable.
// Simple type alias
type ID = string | number; // Union type: can be string OR number
let userId: ID = "abc123";
let orderId: ID = 456;
// Object type alias
type Point = {
x: number;
y: number;
};
let origin: Point = { x: 0, y: 0 };
// Function type alias
type MathOperation = (a: number, b: number) => number;
let multiply: MathOperation = (a, b) => a * b;
Enums
Enums define a set of named constants, making code more readable and less error-prone.
// Numeric enum (values auto-increment from 0)
enum Direction {
Up, // 0
Down, // 1
Left, // 2
Right // 3
}
let move: Direction = Direction.Up;
// String enum
enum Status {
Pending = "PENDING",
Approved = "APPROVED",
Rejected = "REJECTED"
}
let orderStatus: Status = Status.Pending;
console.log(orderStatus); // "PENDING"
Generics
Generics allow you to write reusable code that works with multiple types while maintaining type safety.
// Generic function
function getFirst<T>(arr: T[]): T | undefined {
return arr[0];
}
// TypeScript infers the type
let firstNum = getFirst([1, 2, 3]); // Type: number
let firstStr = getFirst(["a", "b"]); // Type: string
// Generic interface
interface Box<T> {
value: T;
}
let numberBox: Box<number> = { value: 42 };
let stringBox: Box<string> = { value: "hello" };
π‘οΈ Why Use TypeScript?
1. Catch Errors Early
Many bugs are caught during development, before the code even runs. This saves debugging time.
2. Better IDE Support
Get intelligent code completion, inline documentation, and refactoring tools that understand your code.
3. Self-Documenting Code
Type annotations serve as documentation, making code easier to understand and maintain.
4. Safer Refactoring
When you change a function signature, TypeScript shows you everywhere that needs updating.
β οΈ Common TypeScript Types
| Type | Description | Example |
|---|---|---|
string |
Text values | let name: string = "John"; |
number |
All numbers (int, float) | let age: number = 30; |
boolean |
true or false | let active: boolean = true; |
string[] |
Array of strings | let names: string[] = ["a", "b"]; |
any |
Disables type checking | let data: any = "anything"; |
void |
Function returns nothing | function log(): void { } |
null |
Intentionally empty | let empty: null = null; |
undefined |
Not yet assigned | let x: undefined; |
object |
Non-primitive type | let obj: object = {}; |
unknown |
Type-safe version of any | let input: unknown; |
π Getting Started with TypeScript
Installation
# Install TypeScript globally
npm install -g typescript
# Check the version
tsc --version
# Initialize a TypeScript project
tsc --init
Compiling TypeScript
# Compile a single file
tsc myfile.ts
# Watch mode (auto-compile on save)
tsc myfile.ts --watch
# Compile all files in project
tsc
π Type Inference
TypeScript can often infer types automatically, so you don't always need explicit annotations.
// TypeScript infers the types
let message = "Hello"; // Inferred as string
let count = 42; // Inferred as number
let active = true; // Inferred as boolean
let nums = [1, 2, 3]; // Inferred as number[]
// Function return type inferred
function double(n: number) {
return n * 2; // Return type inferred as number
}
// Explicit types useful when:
// 1. Declaration without initialization
let username: string;
// 2. Function parameters (always required)
function greet(name: string) { }
// 3. Complex objects
let config: { port: number; host: string };
β When to Use JavaScript vs TypeScript
β Use JavaScript When:
- Building quick prototypes
- Small scripts or utilities
- Learning web development
- Team isn't familiar with types
- Project is simple and short-lived
β Use TypeScript When:
- Building large applications
- Working with a team
- Long-term maintainable code needed
- Complex data structures
- API integrations
π‘ Best Practices
- Start with strict mode - Enable
"strict": truein tsconfig.json - Avoid
any- It defeats the purpose of TypeScript - Use interfaces for objects - Makes code more readable and maintainable
- Let TypeScript infer - Don't over-annotate when types are obvious
- Use union types - For values that can be multiple types
- Enable IDE integration - Use VS Code for best TypeScript experience
π Quick Reference
TypeScript Cheat Sheet
// Basic Types
let str: string = "hello";
let num: number = 42;
let bool: boolean = true;
let arr: number[] = [1, 2, 3];
// Function with types
function fn(param: string): number { }
// Interface
interface User { name: string; age: number; }
// Type alias
type ID = string | number;
// Generic
function wrap<T>(value: T): T[] { }
- TypeScript is JavaScript with types added
- Types are checked at compile time, not runtime
- TypeScript compiles down to plain JavaScript
- Interfaces define object shapes
- Generics create reusable, type-safe code
- Type inference reduces the need for explicit types
- Use TypeScript for larger, team-based projects
- All JavaScript code is valid TypeScript