Why TypeScript?
TypeScript adds optional static typing to JavaScript. This means you catch bugs at compile time — before they reach your users — and get much better IDE support with autocomplete and inline documentation. The learning curve is gentler than it looks, especially if you already know JavaScript.
Setting Up TypeScript in 5 Minutes
- Install TypeScript globally or as a dev dependency:
npm install --save-dev typescript ts-node npx tsc --init - This creates a
tsconfig.json. Key settings to know:{ "compilerOptions": { "target": "ES2020", "module": "CommonJS", "strict": true, "outDir": "./dist", "rootDir": "./src" } } - Rename your
.jsfiles to.tsand start the compiler watcher:npx tsc --watch
Core Concept 1: Basic Types
TypeScript's basic types mirror JavaScript primitives but are declared explicitly:
let username: string = "Alex";
let age: number = 30;
let isActive: boolean = true;
let scores: number[] = [90, 85, 78];
let anything: unknown = "could be anything";
Use unknown instead of any — it forces you to type-check before using the value, keeping your code safe.
Core Concept 2: Interfaces
Interfaces define the shape of an object. They're one of TypeScript's most useful features:
interface User {
id: number;
name: string;
email: string;
role?: 'admin' | 'editor' | 'viewer'; // optional field
}
function greetUser(user: User): string {
return `Hello, ${user.name}!`;
}
The ? makes a field optional. The pipe | creates a union type — the value must be one of those strings.
Core Concept 3: Type Aliases
Type aliases are similar to interfaces but more flexible — they can represent primitives, unions, tuples, and more:
type Status = 'pending' | 'active' | 'archived';
type Coordinates = [number, number]; // tuple
const location: Coordinates = [48.8566, 2.3522];
Core Concept 4: Functions with Types
Always type your function parameters and return values:
function add(a: number, b: number): number {
return a + b;
}
// Arrow function
const multiply = (a: number, b: number): number => a * b;
// Async function
async function fetchUser(id: number): Promise<User> {
const res = await fetch(`/api/users/${id}`);
return res.json();
}
Core Concept 5: Generics
Generics let you write reusable, type-safe functions without losing type information:
function getFirst<T>(arr: T[]): T | undefined {
return arr[0];
}
getFirst([1, 2, 3]); // returns number
getFirst(["a", "b", "c"]); // returns string
TypeScript in React
If you're using React, create your project with TypeScript from the start:
npm create vite@latest my-app -- --template react-ts
Type your component props with an interface:
interface ButtonProps {
label: string;
onClick: () => void;
disabled?: boolean;
}
export function Button({ label, onClick, disabled = false }: ButtonProps) {
return <button onClick={onClick} disabled={disabled}>{label}</button>;
}
Tips for the Transition
- Enable
"strict": truefrom day one — it catches the most bugs - Avoid
any— useunknownwhen the type is truly dynamic - Let TypeScript infer types when possible; only annotate when needed
- Use the VS Code TypeScript integration — hover over anything to see its inferred type
You Already Know Most of It
TypeScript is a superset of JavaScript — every valid JavaScript file is also a valid TypeScript file. The types you add are just annotations; at runtime, they're stripped out completely. Start small, add types incrementally, and you'll quickly see the payoff in fewer runtime errors and a much better development experience.