Language comparison
TypeScript vs JavaScript
TypeScript is not a competing language — it is JavaScript with a static type layer that gets compiled away. The real question is whether your project benefits from that type layer.
TL;DR
- JavaScript — the language browsers and Node.js run. Dynamic types: a variable's type is whatever it currently holds.
- TypeScript — a strict superset of JavaScript that adds optional static types, checked at compile time, erased at runtime.
- The runtime is identical. TypeScript's value lives in your editor, your CI, and the next developer's brain — not at runtime.
Side-by-side comparison
| Aspect | JavaScript | TypeScript |
|---|---|---|
| Type system | Dynamic, runtime | Static, compile-time (optional, gradual) |
| Runtime | Runs in browsers / Node directly | Compiles to JS, then runs |
| Build step | None required | Required (tsc, esbuild, swc) |
| Editor tooling | Good (modern editors infer some) | Excellent — autocomplete, refactor, types everywhere |
| Error timing | Runtime — errors appear when code runs | Compile time — many errors caught before running |
| Onboarding | Lower — fewer concepts | Higher — generics, narrowing, conditional types |
| Refactoring safety | Find/replace; runtime catches misses | Rename across files; compiler catches misses |
| Library ecosystem | Native npm | Same npm; types via DefinitelyTyped (@types/*) or bundled |
| Best for | Tiny scripts, prototypes, simple sites | Apps, libraries, anything that lives more than a month |
Code side-by-side
A function that takes a user and returns their full name:
JavaScript
function fullName(user) {
return user.first + ' ' + user.last;
}
fullName({ first: 'Ada', last: 'Lovelace' });
// → 'Ada Lovelace'
fullName('Ada');
// → 'Ada undefined' (no error until runtime) TypeScript
interface User {
first: string;
last: string;
}
function fullName(user: User): string {
return user.first + ' ' + user.last;
}
fullName({ first: 'Ada', last: 'Lovelace' });
// → 'Ada Lovelace'
fullName('Ada');
// ✗ Type error: string is not User
// (caught before code ever runs) When JavaScript is enough
- Tiny scripts or one-off utilities. Adding a build step to a 30-line script is overhead.
- Throwaway prototypes. If the code might be deleted next week, types slow you down.
- You are still learning JavaScript itself. Master the language first; add types when you understand what they would constrain.
- Static sites with minimal interactivity. A few event handlers do not need a type system.
- Build-step constraints. Embedded environments where you cannot run a compiler.
When TypeScript wins
- Any team larger than one developer. Types are documentation that cannot go out of date.
- Codebase that lives more than a few months. Refactoring is dramatically safer with the compiler watching.
- Libraries. Users of your library get autocomplete and type-checked usage for free.
- API boundaries. Generate types from your OpenAPI or GraphQL schema; client and server stay in sync.
- Complex domain logic. Discriminated unions and exhaustive checks catch entire bug categories.
English phrases engineers use
JavaScript conversations
- "It's a dynamically typed language — the variable can change shape."
- "This is a truthy / falsy check, not a strict comparison."
- "Watch out for type coercion with
==— use===." - "JSDoc comments give us some IDE help without a build step."
- "It's plain JS — no build pipeline required."
TypeScript conversations
- "This needs a discriminated union so we exhaust all cases."
- "The compiler is narrowing the type inside this if block."
- "Don't cast with `as` — that bypasses the check; refactor the types instead."
- "We need to turn on strict in tsconfig; implicit any is hiding bugs."
- "Generics on the response wrapper — let consumers specify the data shape."
Quick decision tree
- Learning to code from scratch → Start with JavaScript, add TypeScript after 2–3 months
- Building a production app → TypeScript
- Authoring an npm library → TypeScript (consumers expect types)
- Throwaway script < 100 lines → JavaScript
- Migrating a legacy codebase → Gradual TS adoption (allowJs + // @ts-check)
- Small static site, few interactions → JavaScript
- Embedded / no build environment → JavaScript
- Team is split → TypeScript with strict: false — ratchet up over time
Frequently asked questions
Is TypeScript a different language from JavaScript?
TypeScript is a strict syntactic superset of JavaScript — every valid JavaScript program is also valid TypeScript. TypeScript adds optional static types and a few language features (enums, decorators, namespaces) on top. After compilation, the type annotations are stripped and what runs in the browser or Node is plain JavaScript.
Does TypeScript run in the browser?
No. Browsers and Node.js only execute JavaScript. TypeScript must be compiled (transpiled) to JavaScript first, typically via tsc, esbuild, swc, or a bundler like Vite or webpack. The compilation step is fast — milliseconds per file with modern tools.
Is TypeScript slower than JavaScript at runtime?
No — at runtime they are identical, because TypeScript IS JavaScript after compilation. Types are erased. The only "cost" is the compile step, which happens during development and CI, not when users run your code.
Should I learn JavaScript before TypeScript?
Yes. TypeScript builds on JavaScript fundamentals (functions, scope, async, prototype chain, this). You will use those concepts every day. Learn them first; then add types on top — that path is much faster than diving directly into TypeScript and being confused about whether something is a JS feature or a TS feature.
When does TypeScript pay off?
For any codebase larger than a few hundred lines or any team larger than one developer. Types catch a class of bugs before runtime, document intent for the next reader, and unlock far better editor tooling (autocomplete, refactor, find-references). The payoff scales with codebase size and time spent maintaining it.
What is the "any" type and why do people warn against it?
`any` opts out of type checking — values typed `any` accept any operation without errors. Using it strategically (third-party JS, gradual migration, prototype code) is fine. Using it routinely defeats the purpose of TypeScript. Many teams enable `noImplicitAny` and `strict` to make accidental `any` impossible.
Can I add TypeScript to an existing JavaScript project gradually?
Yes — this is the most common adoption path. Add tsconfig.json with `allowJs: true`, rename one file from .js to .ts, fix the errors, repeat. `// @ts-check` in .js files lets you type-check without renaming. Most teams reach majority-TypeScript over a few months without a big-bang rewrite.