TypeScript is a superset of JavaScript: every valid JavaScript program is valid TypeScript, and the type annotations are removed when the code is compiled. The question is not which language is better, but whether the extra step is worth it for your project.
What TypeScript gives you
- Errors caught before runtime, like calling a function with the wrong arguments or reading a property that might be undefined.
- Much better editor support: accurate autocomplete, inline documentation and safe renames across a codebase.
- Types that act as living documentation for APIs, props and data models.
- Easier refactoring, because the compiler shows everything a change breaks.
What it costs
- A build or type-check step, plus a tsconfig.json to maintain.
- A learning curve for generics and advanced types.
- Occasional friction with libraries that have weak or missing type definitions.
The build cost keeps shrinking. Recent Node.js versions can run many .ts files directly by stripping the types, and most frameworks support TypeScript out of the box.
When plain JavaScript is fine
- Small scripts, quick prototypes and one-off automation.
- Learning the basics of programming, where fewer concepts help.
When TypeScript pays off
- Codebases that will live longer than a few months.
- Teams with more than one developer.
- Projects with complex data shapes, such as API clients, ORMs and front-end state.
What a type error looks like in practice
Imagine a function that formats a price, and a teammate later passes it a string from a form field instead of a number:
function formatPrice(amount: number): string {
return `$${amount.toFixed(2)}`;
}
const input = "19.5"; // from a form field
formatPrice(input);
// Error: Argument of type 'string' is not assignable to parameter of type 'number'.
In plain JavaScript, that bug only appears when someone runs that exact code path, and the error, toFixed is not a function, points at the wrong line. TypeScript flags it the moment it is typed, with the fix obvious from the message. Multiply that by every function and object shape in a codebase and you can see where the time savings come from.
What TypeScript doesn’t do
Types disappear when the code runs, so TypeScript can’t check data that arrives from outside: API responses, form input, files or environment variables. If an API suddenly returns null where your type says string, the compiler won’t know. Teams solve this by validating data at the edges with a library such as Zod, then trusting the types inside the app. TypeScript also doesn’t make code faster; the compiled JavaScript runs exactly like hand-written JavaScript.
Migrating an existing project
A good middle ground for existing projects is to enable checkJs and JSDoc comments, then migrate files to .ts gradually. A path that works for most teams:
- Add a tsconfig.json with allowJs turned on, so .js and .ts files can live side by side.
- Convert the files that change most often or cause the most bugs first, such as API clients and shared utilities.
- Start with strict mode off if the codebase is large, then switch on strict checks one at a time.
- Avoid sprinkling the any type to silence errors. Each one is a hole in the safety net; use unknown and narrow it instead.
What we think
For anything beyond a throwaway script, TypeScript usually repays its setup cost within weeks, mostly through fewer silly bugs and safer refactors. The tooling has matured to the point where the old objections about slow builds and complex configuration apply far less than they did a few years ago.