Suggest an editImprove this articleRefine the answer for “Why TypeScript is needed, pros and cons”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**TypeScript** is a superset of JavaScript that adds static types, catching errors in your editor before the code runs. ```typescript let age: number = 25; age = "25"; // Error: Type 'string' is not assignable to type 'number' ``` **Key point:** types disappear after compilation; browsers and Node.js execute plain JavaScript.Shown above the full answer for quick recall.Answer (EN)Image**TypeScript** is a superset of JavaScript that adds static types and catches type errors before your code ever runs. ## Theory ### TL;DR - JavaScript crashes at runtime when you pass the wrong data type; TypeScript flags it in your editor while you type - Analogy: JavaScript is like writing a check without a balance check; TypeScript is banking software that blocks the overdraft before you submit - TypeScript compiles to plain JavaScript, so browsers and Node.js run it unchanged - Use TS for teams of 5+ or codebases over 10k lines; skip it for quick one-off scripts ### Quick Example ```typescript // JavaScript: no warning here, crash happens at runtime let userAge = 25; userAge = "25"; console.log(userAge.toFixed(0)); // TypeError: userAge.toFixed is not a function // TypeScript: your editor flags this immediately let userAge: number = 25; userAge = "25"; // Error: Type 'string' is not assignable to type 'number' console.log(userAge.toFixed(0)); // Never reached - blocked at compile time ``` In the JS version the bug lives undetected until it hits production. TypeScript moves that moment to your editor, before any code ships. ### Key Difference JavaScript checks types when code actually runs. TypeScript layers structural type checking on top, so your IDE spots mismatches the moment you type them. According to the TypeScript team at Microsoft, this shift cuts bugs by 15-20% in large codebases. Runtime panics become editor notices. ### When to Use - Solo prototype under 1k lines - stick with JS; the setup overhead does not pay off - Team project or React/Vue/Next.js app - use TS; catches wrong props before the browser does - Node.js API with request validation - use TS; validates data shapes before they hit the database - Legacy JS codebase - migrate incrementally with `allowJs: true`; no need to rewrite everything at once - Quick automation script - JS is faster to iterate ### How the Compiler Handles This TypeScript's compiler (`tsc`) parses your `.ts` files, runs structural type checking (if two objects have matching shapes, their types are compatible), then emits plain `.js` files targeting ES5 or ES6. In VSCode, the TypeScript Language Service runs in the background and provides real-time diagnostics without a full compile step. Types disappear completely in the output. Node.js and browsers never see them. ### Common Mistakes **Mistake 1: `any` everywhere** ```typescript // Wrong: defeats the point of using TypeScript function processData(data: any) { return data.foo.bar; // Runtime crash, just like plain JS } // Right: use unknown and narrow it explicitly function processData(data: unknown) { if (typeof data === 'object' && data !== null && 'foo' in data) { return (data as { foo: { bar: string } }).foo.bar; } } ``` `any` turns off all type checking for that value. You lose every benefit. Use `unknown` instead and narrow the type down. **Mistake 2: Skipping `strictNullChecks`** ```typescript // Wrong (strictNullChecks: false in tsconfig) let user = getUser(); user.name.toUpperCase(); // Crashes if user is null // Right (strictNullChecks: true) let user = getUser(); user?.name?.toUpperCase(); // Safe ``` Without `strictNullChecks`, TypeScript lets `null` and `undefined` pass anywhere. Most runtime crashes are still hiding. Enable strict mode from day one. **Mistake 3: Mixing up `interface` and `type`** ```typescript // interface: supports declaration merging interface User { name: string } interface User { age: number } // Merges automatically: { name: string; age: number } // type: no merging, better for unions and intersections type Status = 'active' | 'inactive'; type AdminUser = User & { role: 'admin' }; ``` Many teams default to `interface` for object shapes and `type` for unions and compositions. Both work; the difference shows up when you need to extend or compose types. ### Real-World Usage - **React / Next.js** - typed component props: `interface Props { user: User }` - **Express / NestJS** - DTOs that validate request shapes before touching the database - **Redux Toolkit** - `PayloadAction<User>` keeps action payloads predictable - **Node.js** - `@types/node` provides type definitions for the standard library ### Follow-up Questions **Q:** What is structural typing in TypeScript? **A:** Two types are compatible if their shapes match, regardless of their names. An object with `{ x: number }` satisfies any type that requires `{ x: number }`, even without an explicit declaration. **Q:** How does TypeScript handle JavaScript libraries without types? **A:** It uses `@types/` packages, for example `@types/react` or `@types/node`. These are `.d.ts` declaration files that describe the shape of a library without shipping TypeScript source. **Q:** Should you always enable strict mode? **A:** Yes, in new projects. `strict: true` in `tsconfig.json` enables `strictNullChecks`, `noImplicitAny`, and several other checks that catch the most common bugs. Turning them off gives you TypeScript in name only. **Q:** How do you migrate a JavaScript project to TypeScript without breaking CI? **A:** Set `allowJs: true` and `checkJs: false` in `tsconfig.json`. Add `// @ts-check` to individual files as you go. This lets `.js` and `.ts` files coexist in the same project during the transition. ## Examples ### Typed React Component ```typescript interface UserProps { id: number; name: string; isAdmin: boolean; } const UserCard: React.FC<UserProps> = ({ id, name, isAdmin }) => ( <div> {name} (ID: {id}){isAdmin && <strong> Admin</strong>} </div> ); // TypeScript catches this before the browser loads the component: // <UserCard id="1" name="Alice" isAdmin={false} /> // Error: Type 'string' is not assignable to type 'number' ``` Passing `id="1"` (string) instead of `id={1}` (number) is one of the most common React bugs. TypeScript catches it at compile time. This pattern appears in every Next.js and Remix codebase using typed components. ### Discriminated Union in an API Handler ```typescript type ApiResponse = | { success: true; data: string } | { success: false; error: string }; function handleUser(id: number): ApiResponse { if (id > 0) { return { success: true, data: 'User found' }; } return { success: false, error: 'Invalid ID' }; } const result = handleUser(1); if (result.success) { console.log(result.data); // TypeScript knows 'data' exists here } else { console.log(result.error); // And 'error' exists here } ``` The `success` field acts as a discriminator. TypeScript narrows the type inside each branch, so accessing `.data` on the error branch is a compile-time error, not a runtime surprise. This pattern shows up constantly in NestJS and Express handlers. For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.