TypeScript vs JavaScript: When to Use Which
Introduction
The TypeScript vs JavaScript debate is mostly settled in the professional web development world — TypeScript won. But "TypeScript won" doesn't mean "always use TypeScript for everything without thinking." There are still legitimate cases where JavaScript is the correct choice, and there are TypeScript setups that are so permissive they might as well be JavaScript anyway.
This post is about making the decision thoughtfully. What does TypeScript actually give you? What does it cost? When is that cost worth it, and when isn't it?
Core Concepts
What TypeScript Actually Is
TypeScript is a superset of JavaScript. Every valid JavaScript file is valid TypeScript. TypeScript adds a static type system — types are checked at compile time and stripped before the code runs. At runtime, it's JavaScript.
// TypeScript — compiled away at runtime
function greet(name: string): string {
return "Hello, " + name + "!";
}
// After compilation — this is what actually runs
function greet(name) {
return "Hello, " + name + "!";
}No TypeScript code reaches the browser or Node.js runtime. The types are documentation and a compile-time verification tool, nothing more.
What TypeScript Costs
- Setup time —
tsconfig.jsonconfiguration, build pipeline setup - Learning curve — generics, utility types, declaration files
- Compile step — build time, watch mode, source maps
- Third-party types — many packages require
@types/*declarations - Boilerplate — interfaces, type annotations, explicit generics
These costs are real. For a 50-line script you're writing this afternoon, they outweigh the benefits.
When to Use TypeScript
Large or Growing Codebases
The ROI of TypeScript scales with codebase size. A 500-line application has a small surface area — you can hold most of it in your head. A 50,000-line application cannot be held in anyone's head. Types serve as machine-checked documentation that travels with the code.
// Without types — what does options look like?
async function createUser(options) {
// ...
}
// With types — immediately clear, IDE-assisted
interface CreateUserOptions {
name: string;
email: string;
role: 'admin' | 'user' | 'guest';
metadata?: Record<string, unknown>;
}
async function createUser(options: CreateUserOptions): Promise<User> {
// TypeScript will catch if you access options.username instead of options.name
}Team Projects
When multiple developers work on a codebase, TypeScript dramatically reduces the "I didn't know this function expected that shape" class of bugs. It also makes refactoring safe — change a type definition and TypeScript shows you every call site that needs updating.
Projects with Longevity
TypeScript pays off proportionally to how long the project lives. Code you wrote six months ago becomes unfamiliar. Types serve as a contract that remains legible even after you've forgotten the details.
// ...more examples as needed...