TypeScript vs JavaScript Explained
TypeScript is JavaScript plus static types. Compare the two languages across type checking, error detection, tooling, and real-world development.
TypeScript is JavaScript plus static types. The main difference is when errors are caught: TypeScript finds type mistakes while you write code, before it ever runs. JavaScript only surfaces those same mistakes when the affected line executes, which could be in production.
Everything else about the runtime, the syntax, and the ecosystem is the same. TypeScript adds a compile-time safety check and then steps out of the way.
Side-by-Side Comparison
| Feature | JavaScript | TypeScript |
|---|---|---|
| Type checking | Dynamic, at runtime | Static, at compile time |
| Error detection | When code executes | In the editor, before running |
| Type annotations | None | Optional (: string, : number, and so on) |
| Compilation | None needed | Compiles to JavaScript via tsc |
| Editor autocomplete | Limited, best-guess | Precise, type-driven |
| Refactoring support | Basic find-and-replace | Safe rename across the project |
| Runtime behavior | Runs directly in browser/Node.js | Identical to JS after compilation |
| File extensions | .js, .mjs, .cjs | .ts, .tsx, .mts, .cts |
| Adoption path | None needed | Gradual, one file at a time |
The most important row is runtime behavior: it is identical. TypeScript does not make your code faster or slower. It only checks it.
Type Checking: The Core Difference
The biggest practical difference is when you learn about mistakes.
Here is the same bug in both languages:
// JavaScript - no error until runtime
const user = { name: "Alex", age: 28 };
console.log(user.username);JavaScript runs this without complaint. user.username is undefined because the property is actually name. You might not notice the bug until something downstream breaks.
// TypeScript - error in the editor immediately
const user = { name: "Alex", age: 28 };
console.log(user.username);TypeScript catches this typo at compile time instead of waiting for it to fail at runtime. It reports the exact error before the code ever runs:
Property 'username' does not exist on type '{ name: string; age: number; }'.
Did you mean 'name'?The compiler spots the typo instantly. It even suggests the correct property name. You fix the bug before you ever run the code.
Function Calls and Arguments
JavaScript lets you pass anything to any function. TypeScript tells you when the arguments do not match.
JavaScript:
function add(a, b) {
return a + b;
}
add(5, 10); // 15 (works)
add(5, "10"); // "510" (string concatenation, probably a bug)
add(5); // NaN (missing argument, probably a bug)All three calls run without error, but only the first one does what you expect. The other two produce subtle bugs.
TypeScript:
function add(a: number, b: number) {
return a + b;
}
add(5, 10); // 15 (works)
add(5, "10"); // Compiler error: string is not number
add(5); // Compiler error: expected 2 arguments, got 1TypeScript rejects the second and third calls at compile time. The code never runs with bad data. You get clear error messages that point directly at the problem.
Handling Missing Values
JavaScript's null and undefined are a common source of runtime crashes. TypeScript's strict mode helps you handle them safely.
JavaScript:
function getLength(str) {
return str.length;
}
getLength("hello"); // 5
getLength(null); // TypeError: Cannot read properties of nullThe second call crashes at runtime because null has no .length. If this happens in production, your user sees a broken page.
TypeScript (with strictNullChecks enabled):
function getLength(str: string) {
return str.length;
}
getLength("hello"); // 5
getLength(null); // Compiler error: null is not stringTypeScript does not let you pass null where a string is expected. To handle values that might be null, you must write a check:
function getLength(str: string | null) {
if (str === null) {
return 0;
}
return str.length;
}The string | null type explicitly says "this might be null." The compiler then requires the null check. You cannot forget.
Development Experience
TypeScript improves the editor experience itself. Because the compiler understands every variable, function, and object in your project, your editor can offer precise help.
In JavaScript, autocomplete on an object shows common property guesses. In TypeScript, it shows exactly which properties exist:
type User = {
id: number;
name: string;
email: string;
};
function sendEmail(user: User) {
// Typing "user." shows only id, name, and email. No guessing.
}Renaming a variable in JavaScript means find-and-replace, which can miss references or change unrelated code. In TypeScript, the rename command knows every reference to that symbol and only changes those.
The Compile Step
TypeScript adds a build step: you run tsc (the TypeScript compiler) to convert .ts files into .js files.
npm install -g typescript
tsc app.ts # produces app.jsThe compiler does two things:
- Checks all your types. If there are errors, it reports them.
- Removes the type annotations and outputs plain JavaScript.
Type annotations are always stripped. They never appear in the output. For more on compilation, see how to run TypeScript from the command line.
When to Use Each
Use JavaScript when:
- You are writing a small, single-file script.
- The project is a quick prototype you plan to throw away.
- Your team is not yet comfortable with TypeScript.
Use TypeScript when:
- The project will grow beyond a few files.
- Multiple people will work on the code.
- You want to catch bugs before they reach users.
- You value editor autocomplete and safe refactoring.
Most professional teams use TypeScript for new projects. The compile step adds a few seconds of build time during development, but it saves hours of debugging. For a closer look at how TypeScript prevents real bugs, see how TypeScript helps catch bugs early.
Rune AI
Key Insights
- TypeScript is a superset of JavaScript. All JavaScript is valid TypeScript.
- TypeScript catches type errors at compile time. JavaScript only finds them at runtime.
- Both languages produce identical runtime behavior. TypeScript types are erased during compilation.
- TypeScript editor support is significantly better, with autocomplete, inline errors, and refactoring.
- Start new projects in TypeScript. Use JavaScript for tiny scripts or when the team is not ready.
Frequently Asked Questions
Can I use JavaScript libraries in TypeScript?
Is TypeScript slower than JavaScript?
Should I start new projects in TypeScript or JavaScript?
Conclusion
TypeScript and JavaScript are not competitors. TypeScript is JavaScript with a safety net. You get the same runtime behavior, the same ecosystem, and the same flexibility, plus compile-time type checking that catches mistakes early. For projects of any meaningful size, the trade-off is strongly in TypeScript's favor.
More in this topic
TypeScript Compiler Explained
The TypeScript compiler (tsc) turns .ts files into .js files while checking types. Learn what it does, how to use it, and how it fits your workflow.
Set Up ESLint for TypeScript
Install and configure ESLint with typescript-eslint to catch bugs and enforce consistent code style in your TypeScript project.
Pick Utility Type in TypeScript
Pick creates a new type by selecting only the properties you name from an existing type. Use it to build focused types for specific views, API responses, or function parameters.