TypeScript Explained: Why Developers Are Switching from Plain JavaScript
Development

TypeScript Explained: Why Developers Are Switching from Plain JavaScript

M
Marcus Thorne · ·7 min read

JavaScript runs the web. It’s in every browser, every web framework, and increasingly on servers through Node.js. But JavaScript has a well-known weakness: it lets you do things that obviously shouldn’t work, and only tells you about it when something crashes at runtime.

TypeScript was built to fix that. It’s now one of the most popular languages in professional software development, and understanding it is increasingly expected for any serious web or Node.js developer.

What TypeScript Is

TypeScript is JavaScript with a type system layered on top. It’s a superset: every valid JavaScript file is also valid TypeScript. You add TypeScript gradually — you don’t have to rewrite everything at once.

TypeScript code gets compiled to plain JavaScript before running. Browsers and Node.js don’t run TypeScript directly; the TypeScript compiler (tsc) strips out the type annotations and produces the JavaScript your runtime actually executes.

The key point: TypeScript only affects development time. At runtime, it’s just JavaScript. TypeScript’s value is entirely in the feedback it gives you while you’re writing code.

The Problem TypeScript Solves

Here’s a classic JavaScript footgun:

function greet(user) {
  return `Hello, ${user.name}`;
}

greet(42); // runs without error, produces "Hello, undefined"

JavaScript accepts this. You won’t find out something is wrong until the function runs in production and produces garbage output — or crashes trying to access a property on a number.

With TypeScript:

function greet(user: { name: string }) {
  return `Hello, ${user.name}`;
}

greet(42); // Error: Argument of type 'number' is not assignable to parameter

The error appears in your editor, before you save, before you run anything. The problem is caught immediately instead of in production.

How TypeScript Works

Type Annotations

You declare what types variables and function parameters should be:

let age: number = 25;
let name: string = "Alice";
let active: boolean = true;

TypeScript also infers types when you don’t annotate:

let count = 0; // TypeScript infers: number
count = "hello"; // Error: Type 'string' is not assignable to type 'number'

You don’t have to annotate everything — TypeScript figures out a lot from context.

Interfaces and Types

You can define the shape of objects:

interface User {
  id: number;
  name: string;
  email: string;
  role: "admin" | "editor" | "viewer";
}

function getUser(id: number): User {
  // must return an object matching the User shape
}

If your function returns something that doesn’t match User, TypeScript flags it immediately.

Union Types

Variables can accept multiple types:

function formatId(id: number | string) {
  return id.toString();
}

TypeScript tracks which type you’re working with inside conditionals:

function process(input: number | string) {
  if (typeof input === "string") {
    return input.toUpperCase(); // TypeScript knows it's a string here
  }
  return input * 2; // TypeScript knows it's a number here
}

This is called type narrowing, and it’s one of TypeScript’s more useful features.

Generics

Generics let you write reusable code that works with any type while preserving type safety:

function firstItem<T>(arr: T[]): T | undefined {
  return arr[0];
}

const num = firstItem([1, 2, 3]); // TypeScript knows: number | undefined
const str = firstItem(["a", "b"]); // TypeScript knows: string | undefined

You get the flexibility of dynamic code with the safety of specific types.

What TypeScript Catches

The practical payoff of TypeScript is catching errors that would otherwise hide until runtime:

Typos in property names:

const user = { firstName: "Alice", lastName: "Smith" };
console.log(user.firstname); // Error: Property 'firstname' does not exist — did you mean 'firstName'?

Wrong function arguments:

function add(a: number, b: number) { return a + b; }
add(1, "2"); // Error: Argument of type 'string' is not assignable to 'number'

Null/undefined access:

const user = getUser(id); // returns User | null
console.log(user.name); // Error: Object is possibly 'null'

// TypeScript forces you to check:
if (user) {
  console.log(user.name); // safe
}

Refactoring confidence: When you rename a function or change its signature, TypeScript immediately shows every call site that needs updating. Without types, you have to find them all manually and hope you caught everything.

TypeScript and Your Editor

TypeScript’s biggest quality-of-life improvement might be IDE integration. VS Code has TypeScript support built in — you get:

  • Autocomplete that knows the exact properties and methods available on any object
  • Inline error highlighting before you run anything
  • Hover documentation that shows type signatures
  • “Go to definition” that works accurately across your entire codebase
  • Refactoring tools that update all references automatically

This level of editor support is largely impossible with plain JavaScript, where the editor can’t know what properties an object might have.

TypeScript vs JavaScript: When to Use Each

Use TypeScript for:

  • Any project larger than a few files
  • Projects with multiple contributors
  • Long-lived codebases that will be maintained and extended
  • Libraries and packages used by others
  • Node.js backends

JavaScript without TypeScript is fine for:

  • Small personal scripts
  • Quick prototypes you’ll throw away
  • Projects where setup overhead isn’t worth it

Most serious JavaScript projects — React apps, Angular apps (which requires TypeScript), large Node.js backends, open source libraries — use TypeScript by default.

Getting Started

TypeScript integrates cleanly into existing JavaScript projects.

Install TypeScript:

npm install --save-dev typescript
npx tsc --init  # creates tsconfig.json

Rename a .js file to .ts and start adding types incrementally. You don’t need to convert everything at once.

If you’re using a framework:

  • React: Create React App and Vite both have TypeScript templates
  • Next.js: TypeScript support is built in, just rename files to .tsx
  • Node.js/Express: Add @types/node and @types/express for type definitions

Learn as you go: TypeScript’s error messages are unusually readable. When you see one you don’t understand, it usually links directly to the TypeScript documentation or has enough context to search for.


TypeScript’s adoption among professional developers isn’t accidental. The upfront cost — learning the syntax, configuring the compiler — pays dividends quickly: fewer bugs in production, a faster feedback loop during development, and dramatically better editor support. If you’re writing JavaScript professionally and haven’t picked up TypeScript yet, it’s time.

M

Written by Marcus Thorne

Software analysis and cybersecurity tips

A former software engineer, Marcus transitioned into tech journalism to explain complex digital concepts in simple terms.

You Might Also Like