Why TypeScript

TypeScript · Essentials · 6 min

Knowing what TypeScript does (and does not do) at runtime shapes every decision you make with it.

TypeScript is a superset of JavaScript: every JavaScript program is syntactically valid TypeScript, and TypeScript adds a way to describe the shapes of values — which properties an object has, what a function takes and returns. A checker reads those descriptions and reports mistakes before the code ever runs.

The key mental model: types are erased. The compiler checks your code, then strips the annotations and emits plain JavaScript. Nothing about types survives at runtime — there is no type information to inspect, no runtime validation of function arguments, no performance change. If data comes from JSON.parse or a network call, TypeScript only knows what you tell it; it cannot verify it.

What you get in exchange:

  • Errors caught early: typos in property names, calling something that might be undefined, passing a string where a number is expected.
  • Editor intelligence: autocomplete, go-to-definition, safe rename and inline docs all come from the same type information.
  • Documentation that can't go stale: a function signature tells the next reader exactly what it accepts.
  • Confident refactoring: change a type and the compiler lists every place that needs updating.

TypeScript is also gradual. You can rename a .js file to .ts, fix a few errors and keep going, and strictness can be raised over time. Its type system is structural: two types are compatible if their shapes match, regardless of their names, which fits how JavaScript code is actually written.

A type error does not stop JavaScript being emitted by default — the checker and the emitter are separate jobs, and many projects let a bundler or runtime strip types while tsc only checks.

Example

// The TypeScript you write:
function greet(user: { name: string; age?: number }): string {
  return `Hello, ${user.name}`;
}

greet({ name: "Ada" });
// @ts-expect-error -- 'nme' does not exist; did you mean 'name'?
greet({ nme: "Ada" });

// The JavaScript that runs (types erased):
// function greet(user) {
//   return `Hello, ${user.name}`;
// }

Remember

  • TypeScript = JavaScript + static types checked before runtime
  • Types are erased: no runtime checks, no runtime cost
  • Typing is structural: compatible shapes, not matching names

Watch out for

  • Assuming TypeScript validates external data (API responses, JSON) at runtime — it does not.

Check yourself

  1. You annotate a parameter as number and a caller passes a value parsed from JSON that is actually a string. What happens at runtime?
  2. Two interfaces with different names declare exactly the same properties. Can a value of one be used where the other is expected?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: www.typescriptlang.org/docs/handbook/typescript-from-scratch.html

Builds on

Nothing: this is a foundation.

Unlocks