Skip to content
TypeScript ts getting-started 4 min read

Why Use TypeScript?

JavaScript is flexible and ubiquitous, but that flexibility is also its weakness: mistakes that a type system would catch instantly slip through to production. TypeScript pays for the small upfront cost of annotations many times over through earlier bug detection, dramatically better editor tooling, fearless refactoring, and self-documenting code. This page makes the case concretely, with examples of bugs TypeScript prevents and the developer-experience wins that follow. If you are still deciding whether it is worth it, this is the page that answers “why.”

Catch bugs before runtime

The most direct benefit is that the compiler finds errors while you write code, not when a user hits them. Type mismatches, misspelled properties, and bad function calls are flagged immediately.

function applyDiscount(price: number, percent: number): number {
  return price - price * (percent / 100);
}

applyDiscount(100, 20);       // ✅ 80
applyDiscount("100", 20);     // ❌ Error: 'string' is not assignable to 'number'
applyDiscount(100);           // ❌ Error: Expected 2 arguments, but got 1

In plain JavaScript, applyDiscount("100", 20) would produce the string "100-..." nonsense or NaN silently. TypeScript refuses to compile it.

Eliminate “undefined is not a function”

The most common JavaScript runtime crash comes from accessing properties on null or undefined. With strictNullChecks on, TypeScript forces you to handle those cases.

interface Config {
  timeout?: number;
}

function getTimeout(config: Config): number {
  // ❌ Error: 'config.timeout' is possibly 'undefined'.
  return config.timeout * 2;
}

function getTimeoutSafe(config: Config): number {
  return (config.timeout ?? 5000) * 2; // ✅ handled
}

The ?. and ?? operators combine with the type system so the compiler can prove a value is present before you use it.

Superior tooling and autocomplete

Because the editor knows the precise type of every value, you get accurate autocomplete, inline parameter hints, hover documentation, and “find all references.” This is often the single biggest day-to-day productivity gain.

type Order = { id: string; total: number; items: string[] };

function summarize(order: Order) {
  // Typing `order.` shows id, total, items — and only those
  return `${order.items.length} items, $${order.total}`;
}

The IDE turns your types into an interactive map of the codebase, which is invaluable when working in code you did not write.

Refactor without fear

Renaming a property, changing a function signature, or restructuring a module are terrifying in large JavaScript codebases. With TypeScript, the compiler points to every place that needs to change.

// Rename `total` -> `totalCents` and the compiler flags every usage
type Invoice = { id: string; totalCents: number };

function format(invoice: Invoice) {
  return (invoice.totalCents / 100).toFixed(2); // updated automatically by tooling
}

Editor-driven “rename symbol” updates all references safely because the type graph is known.

Types as living documentation

A function signature tells you exactly what to pass and what you get back — documentation that can never drift out of date because the compiler enforces it.

ConcernPlain JavaScriptTypeScript
Argument shapeRead the body or hopeStated in the signature
Return valueInspect at runtimeInferred and shown
Refactor safetyManual grepCompiler-verified
OnboardingTribal knowledgeSelf-describing types
Bug detectionRuntime / testsCompile time

The honest trade-offs

TypeScript is not free. There is a build/compile step, a learning curve for advanced types, and occasional friction with poorly-typed third-party libraries. For a tiny throwaway script the overhead may not be worth it; for anything that lives longer than a weekend, the balance tips strongly toward TypeScript.

// You can opt out locally when a library's types fight you — but do it deliberately
const data = JSON.parse(raw) as ApiResponse; // narrow, intentional escape hatch

Avoid sprinkling any to silence the compiler. Each any is a hole in your type safety; prefer unknown plus narrowing, which keeps you honest.

Best Practices

  • Adopt TypeScript for any codebase expected to live beyond a quick prototype.
  • Turn on strict mode to unlock null-safety and the strongest guarantees.
  • Use the editor’s refactoring tools — they are safe precisely because types exist.
  • Let function signatures serve as documentation; keep them precise and honest.
  • Reach for unknown and type guards instead of any when types are uncertain.
  • Treat third-party type friction as a signal to write a small wrapper, not to disable checking globally.
Last updated June 29, 2026
Was this helpful?