TypeScript vs JavaScript
Short answer
TypeScript is JavaScript with a static type system layered on top. You annotate your code, a compiler checks those annotations before the code runs, and then it deletes them and emits plain JavaScript. Nothing about runtime behaviour changes — you get errors at build time that JavaScript would only give you in production.
| JavaScript | TypeScript | |
|---|---|---|
| Runs in the browser directly | Yes | No — compiles to JavaScript first |
| Type checking | At runtime, when it fails | At compile time, before you ship |
| Build step | Optional | Required |
| File extension | .js / .jsx | .ts / .tsx |
| Editor autocomplete | Inferred, often incomplete | Driven by real type information |
| Refactoring safety | Find-and-replace and hope | The compiler finds every call site |
| Runtime behaviour | — | Identical; types are erased |
| Catches typos in property names | No | Yes |
| Validates data from an API | No | No — types are compile-time only |
TypeScript is a superset, and that matters
Every valid JavaScript file is a valid TypeScript file. Rename app.js to app.ts and it compiles — possibly with warnings, but it compiles. This is not a marketing line; it is the design decision that governs everything else. TypeScript adds a layer above JavaScript rather than replacing it, so there is no new runtime, no new standard library, and no behaviour to relearn.
1// JavaScript — valid TypeScript already
2function total(items) {
3 return items.reduce((sum, i) => sum + i.price, 0);
4}
5
6total("hello");
7// → runtime TypeError: items.reduce is not a function
8// You find out when a user finds out.
9
10// TypeScript — the same function with the contract written down
11type Item = { price: number };
12
13function total(items: Item[]): number {
14 return items.reduce((sum, i) => sum + i.price, 0);
15}
16
17total("hello");
18// → Argument of type 'string' is not assignable to parameter
19// of type 'Item[]'. Caught in the editor, before running anything.The gain is not that the second version is safer once it is running — both behave identically at runtime. The gain is when you learn about the mistake. In JavaScript that is when the code executes with that input, which might be in a rarely visited branch, in production, three weeks later.
Types are erased — see the output
Compiling TypeScript is mostly a deletion pass. Type annotations, interfaces, type aliases and generics are removed, and what remains is the JavaScript you would have written by hand. This is worth seeing once, because it makes the runtime consequences obvious rather than theoretical.
1// user.ts
2interface User { id: number; name: string; }
3
4export function greet(user: User): string {
5 return "Hi " + user.name;
6}
7
8// → compiles to user.js:
9// export function greet(user) {
10// return "Hi " + user.name;
11// }
12//
13// The interface is gone entirely. There is no User at runtime,
14// nothing to check against, and no cost in the shipped bundle.1type User = { id: number; name: string };
2
3const res = await fetch("/api/me");
4const user: User = await res.json();
5// → compiles fine, and lies happily if the API returns
6// { id: "7" } — a string where the type promises a number
7
8console.log(user.id.toFixed(2));
9// → TypeError: user.id.toFixed is not a function
10
11// The fix is a runtime check at the boundary:
12const parsed = UserSchema.parse(await res.json()); // zod, valibot…
13// → throws immediately with a useful message, and `parsed`
14// is now typed AND verifiedWhat the type system actually catches
It is worth being specific about the bugs TypeScript prevents, because "catches errors" is too vague to be persuasive. In real codebases, the recurring wins are a small set of very common mistakes.
- →Misspelled property names — user.nmae is a compile error rather than silently undefined.
- →Calling something with the wrong number or order of arguments.
- →Reading a property off a value that might be null or undefined, which strictNullChecks makes explicit.
- →Forgetting to handle a case after adding one to a union — an exhaustive switch fails to compile.
- →Passing the wrong shape into a function three layers down after a refactor.
- →Using an async function's return value without awaiting it.
- →Renaming a field in one place and missing seven others.
1type Status = "idle" | "loading" | "done";
2
3function label(s: Status): string {
4 switch (s) {
5 case "idle": return "Ready";
6 case "loading": return "Working…";
7 case "done": return "Finished";
8 }
9}
10
11// Six months later someone adds "error" to the union above:
12// type Status = "idle" | "loading" | "done" | "error";
13// → Function lacks ending return statement and return type
14// does not include 'undefined'.
15// Every switch over Status in the codebase now fails to compile,
16// which is exactly the list of places you need to edit.That last example is the strongest argument for TypeScript on a team, and it has nothing to do with catching typos. Adding a case to a union hands you a complete, compiler-generated list of everywhere that decision is made. In JavaScript, finding that list is a grep and a guess.
Structural typing, not nominal
TypeScript compares types by shape, not by name. If an object has the properties a type requires, it is assignable to that type — regardless of which interface it was declared with, or whether it was declared with one at all. Developers arriving from Java or C# expect the opposite and find this surprising.
1interface Point { x: number; y: number }
2interface Vector { x: number; y: number }
3
4const p: Point = { x: 1, y: 2 };
5const v: Vector = p;
6// → fine. Same shape, so the names are irrelevant.
7
8function draw(pt: { x: number; y: number }) {}
9draw({ x: 0, y: 0 });
10// → fine, with no interface involved at all
11
12// Excess property checks apply only to fresh object literals:
13const q: Point = { x: 1, y: 2, z: 3 };
14// → Object literal may only specify known properties
15const raw = { x: 1, y: 2, z: 3 };
16const r: Point = raw;
17// → allowed — the extra property is not checked via a variableThis is 1 of 200+ questions in the Complete Frontend Kit
Get every question with detailed answers, follow-ups and real code — plus coding challenges and a last-minute revision sheet. One-time payment, instant access.
⚡ Get the Complete Frontend Kit → ₹499TypeScript in React
React is where most frontend developers meet TypeScript, and it is where the return is highest, because a component's props are a contract between files. Typed props give you autocomplete at every call site, an error when a required prop is missing, and a rename that propagates across the codebase.
1type ButtonProps = {
2 label: string;
3 variant?: "primary" | "ghost";
4 onClick: (e: React.MouseEvent<HTMLButtonElement>) => void;
5};
6
7function Button({ label, variant = "primary", onClick }: ButtonProps) {
8 return <button className={variant} onClick={onClick}>{label}</button>;
9}
10
11<Button label="Save" onClick={handleSave} />;
12// → fine
13<Button onClick={handleSave} />;
14// → Property 'label' is missing in type
15<Button label="Save" variant="danger" onClick={handleSave} />;
16// → Type '"danger"' is not assignable to '"primary" | "ghost"'
17
18const [user, setUser] = useState<User | null>(null);
19// → user.name is an error until you narrow it, which is
20// the null check you would otherwise have forgottenThe variant example is the one to remember for interviews. A union of string literals turns a prop into a closed set of options, so a typo in a variant name fails to compile instead of silently rendering an unstyled button — a class of bug that is nearly invisible in code review.
The honest cost
TypeScript is not free, and pretending otherwise makes for a weak interview answer. There is a build step to configure and keep working. There is a learning curve past the basics — generics, conditional types and the utility types are a genuine second thing to learn. Type errors in library-heavy code can be long and hard to read. And on a small script or a one-week prototype, the setup can plausibly cost more than the bugs it prevents.
| Context | Worth it? | Why |
|---|---|---|
| Team codebase, multiple contributors | Strongly yes | Types are the contract nobody has to remember |
| Long-lived product | Strongly yes | Refactoring safety compounds over years |
| React app of any real size | Yes | Props and state are exactly what types describe well |
| Library you publish | Yes | Consumers get autocomplete and inline docs |
| A 50-line script | No | The config costs more than the bugs |
| Prototype you will throw away | Probably not | Unless you are fast in it already |
| Learning programming from scratch | Not first | Learn the language before the checker |
Should you learn JavaScript or TypeScript first?
JavaScript first, and not for long. TypeScript's type system describes JavaScript's semantics — closures, prototypes, `this`, the difference between null and undefined, how objects are passed by reference. If those are unfamiliar, type errors read as arbitrary compiler complaints rather than as descriptions of something real. Two or three months of solid JavaScript is usually enough before adding types.
For the job market the picture is simpler: in 2026 most frontend roles in India that use React expect TypeScript, job descriptions list it explicitly, and interviewers ask about generics and utility types. Skipping it closes doors. The order is JavaScript to fluency, then TypeScript early — not one instead of the other.
What is changing in 2026
Two shifts are worth knowing about. First, type stripping: Node runs .ts files directly by erasing types without a full compile, and browsers are discussing a similar proposal, which erodes the build-step objection. Second, the TypeScript compiler itself has been ported to Go for a large speed increase, which mainly removes the complaint that checking a big codebase is slow.
Neither changes the fundamentals. Types are still erased, still checked only at compile time, and still no substitute for validating data at your boundaries. But the practical friction of using TypeScript keeps falling, which is why the answer to "should I learn it" has become less debatable each year.
Does TypeScript make my app slower or bigger?
No. Types are removed during compilation, so the shipped bundle is the same JavaScript you would have written. The cost is at build time, in the type-checking step, and in your editor — never at runtime for your users.
What is the difference between interface and type?
Largely interchangeable for object shapes. Interfaces support declaration merging and read more naturally when extended; type aliases can express unions, intersections, tuples and mapped types, which interfaces cannot. A common convention is interfaces for object contracts and types for everything else — but consistency matters more than the choice.
What is the difference between any and unknown?
Both accept any value, but `any` disables checking entirely and lets you call anything on it, while `unknown` forces you to narrow with a typeof, an instanceof, or a type guard before use. `unknown` is the safe choice for genuinely unknown data such as a parsed JSON response.
Do I need TypeScript to get a frontend job?
Increasingly, yes for React roles. Most job descriptions list it, most modern codebases use it, and interviews commonly include typing a component's props or explaining a utility type. JavaScript fundamentals still carry more weight in the interview itself — but the absence of TypeScript filters resumes before that.
Can I use TypeScript with plain JSDoc comments instead?
Yes. With checkJs enabled, the compiler type-checks .js files using JSDoc annotations, giving you most of the checking with no build step and no new file extensions. Several large projects use this, though the syntax is more verbose and advanced types are awkward to express.
Frequently asked questions
- What is the difference between TypeScript and JavaScript?
- TypeScript is JavaScript with an optional static type system. You write type annotations, a compiler verifies them before the code runs, and then removes them to emit plain JavaScript. JavaScript checks types only at runtime, when a mistake has already reached the user.
- Is TypeScript the same as JavaScript?
- It is a strict superset — every valid JavaScript program is a valid TypeScript program. It adds a type layer and nothing to the runtime, so there are no new data structures, no new standard library, and no behavioural differences once compiled.
- Does TypeScript run in the browser?
- No. Browsers execute JavaScript, so TypeScript must be compiled first — by tsc, or more often by a bundler such as Vite, esbuild or SWC that strips the types. Node can now run .ts files directly by erasing types, but the principle is the same.
- Is TypeScript better than JavaScript?
- It is better for codebases that are large, long-lived, or shared between people, because types document contracts and make refactoring safe. For a short script or a throwaway prototype the setup cost can outweigh the benefit. The question is about the project, not the language.
- Should I learn JavaScript or TypeScript first?
- JavaScript first, since TypeScript's types describe JavaScript's semantics — without those, type errors look arbitrary. Two or three months of solid JavaScript is usually enough before adding types, and for React roles you should add them soon after.
- Does TypeScript catch runtime errors?
- No. It catches errors that are detectable from the code itself before it runs — wrong argument types, misspelled properties, unhandled cases. Anything that depends on actual runtime data, like a malformed API response, is invisible to it because types do not exist at runtime.
- Why use TypeScript over JavaScript for React?
- Because a component's props are a contract between files, which is exactly what a type system describes well. You get autocomplete at every call site, an error when a required prop is missing, closed sets of allowed values via string-literal unions, and renames that propagate across the codebase.
- Does TypeScript slow down my application?
- Not at runtime — types are erased, so the output is ordinary JavaScript of the same size. It adds a type-checking step to your build and to your editor's language server, which is where any slowness shows up, and recent compiler work has cut that substantially.
- What is type erasure in TypeScript?
- The compiler removes all type annotations, interfaces, type aliases and generics when it emits JavaScript. Nothing about them survives to runtime, which is why you cannot check a type with an if statement and why external data still needs validating.
- Can I use TypeScript in an existing JavaScript project?
- Yes, incrementally. Enable allowJs so both file types coexist, convert new files and files you are already editing, and leave strict mode off until the initial noise settles. Gradual adoption is a deliberate design goal, not a workaround.
- What is the difference between any and unknown?
- `any` switches off checking for that value, letting you do anything with it and infecting whatever it touches. `unknown` also accepts any value but forbids using it until you narrow it with a check. Use `unknown` for parsed JSON and other untrusted input.
- Is TypeScript required for frontend interviews?
- Not universally, but common for React roles. Expect to type a component's props, explain the difference between interface and type, and use utility types like Partial, Pick and Omit. Core JavaScript still dominates the coding rounds.
This is 1 of 200+ questions in the Complete Frontend Kit
Get every question with detailed answers, follow-ups and real code — plus coding challenges and a last-minute revision sheet. One-time payment, instant access.
⚡ Get the Complete Frontend Kit → ₹499