TypeScript crossed a tipping point: it is now the default language for new JavaScript projects at companies of every size, and the majority of open-source JS libraries ship first-class TypeScript types. Learning it is no longer optional for developers working in the JS ecosystem — it is the baseline expectation. The good news is that TypeScript is not a new language. It is JavaScript with an annotation layer, and you can add that layer gradually.
What changed in 2026
- TypeScript 5.x brought performance improvements and better inference — complex generic types resolve significantly faster; the incremental compile in
watch mode is noticeably snappier.
noUncheckedIndexedAccess is commonly enabled in strict configs — accessing arr[i] returns T | undefined, forcing you to handle missing elements.
- Bun and Deno run TypeScript natively without a compilation step —
bun run server.ts just works.
- AI code assistants generate TypeScript by default. If you can't read typed code, you can't effectively use the output of Copilot or Claude Code.
The mental model
TypeScript adds a type system that runs at compile time, before your code runs. It cannot catch runtime errors caused by network failures or user input — but it eliminates an entire class of bugs caused by wrong data shapes flowing through your code.
// JavaScript — no error until runtime
function greet(user) {
return "Hello, " + user.nme; // typo: nme instead of name — no warning
}
// TypeScript — caught at compile time
function greet(user: { name: string }): string {
return "Hello, " + user.nme; // Error: Property 'nme' does not exist
}
The types you'll use most
// Primitives
let count: number = 0;
let name: string = "Alice";
let active: boolean = true;
// Arrays
let ids: number[] = [1, 2, 3];
let tags: string[] = ["ts", "js"];
// Objects via interface
interface User {
id: number;
name: string;
email?: string; // optional property
}
// Objects via type alias
type Point = { x: number; y: number };
// Union types
type Status = "loading" | "success" | "error";
// Function types
function add(a: number, b: number): number {
return a + b;
}
Interface vs type alias
Both define object shapes. The practical differences:
| Feature |
interface |
type |
| Extending |
extends keyword |
Intersection & |
| Declaration merging |
Yes (useful for augmentation) |
No |
| Primitives and unions |
No |
Yes |
| When to use |
Object shapes, class contracts |
Unions, mapped types, primitives |
Prefer interface for object shapes you'll extend; type for unions, intersections, and utility type compositions. Either is fine; be consistent.
Generics: when and how
Generics let you write reusable code that preserves type information:
// Without generics — loses type info
function first(arr: any[]): any {
return arr[0];
}
// With generics — return type matches input type
function first<T>(arr: T[]): T | undefined {
return arr[0];
}
const num = first([1, 2, 3]); // TypeScript knows: number | undefined
const str = first(["a", "b"]); // TypeScript knows: string | undefined
Don't reach for generics until you've felt the pain of losing type information. That's the signal you need them.
The right tsconfig
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"lib": ["ES2022", "DOM"],
"outDir": "dist",
"rootDir": "src",
"esModuleInterop": true,
"skipLibCheck": true
}
}
strict: true enables 8 flags at once including noImplicitAny and strictNullChecks. Start with it; don't disable it to silence errors — fix the errors.
How to start
- Install:
npm install -D typescript and run npx tsc --init.
- Rename one
.js file to .ts and fix the errors the compiler surfaces.
- Add types to function parameters and return values first — don't annotate local variables, let inference handle them.
- Use the TypeScript playground (typescriptlang.org/play) to experiment without setup.
- Migrate an existing small project file-by-file: set
"allowJs": true and "checkJs": false initially, then flip files one at a time.
Common mistakes
Typing everything explicitly. TypeScript inference is excellent. const x = 5 already has type number — don't write const x: number = 5. Type boundaries (parameters, return values, API responses), not assignments.
Using any to silence errors. any turns off type checking for that value entirely. Use unknown instead — it forces you to narrow before using the value.
Ignoring undefined in arrays. With noUncheckedIndexedAccess enabled, arr[0] is T | undefined. Check before using: if (arr[0] !== undefined).
Type assertions (as) everywhere. as SomeType is a promise to the compiler that you're right. Break that promise and runtime errors follow. Use type guards instead.
Learning TS in isolation. TypeScript is best learned in the context of a real project (React app, Express API). Abstract examples don't teach the tradeoffs.
What to skip
- Decorators until you're working with a framework that requires them (Angular, NestJS).
- Namespace/module syntax — ES modules (
import/export) are the standard.
ts-node for production — compile to JS for production; ts-node is a development convenience only.
- Complex conditional types before you can read a codebase's simpler types fluently — advanced types are a rabbit hole.
FAQ
Do I need to learn JavaScript before TypeScript?
Yes — TypeScript compiles to JavaScript and inherits all its behavior. Learn JS fundamentals (closures, promises, prototypes) first, then layer on TypeScript.
Will TypeScript catch all bugs?
No. It catches type errors at compile time. Runtime errors from unexpected API shapes, network failures, and logical bugs still require tests and runtime validation (e.g., Zod).
Is TypeScript slower to run?
No. TypeScript is erased at compile time — the JS that runs is identical to what you'd have written without types. The compiler itself runs as a build step.
How long does it take to become fluent?
The basics (types, interfaces, enums, generics) take 2–4 weeks with daily use. Advanced patterns (conditional types, infer, template literal types) take months and aren't needed for most apps.
Where to go next