What TypeScript is

TypeScript is JavaScript with an extra layer: you can say what type of value a variable, a parameter or a function result holds, and a tool checks that the code keeps those promises. The JavaScript topic already introduces it under Adding types; this topic goes into depth. Microsoft created it, it is open source (Apache 2.0 license) and it was first released publicly in October 2012.

TypeScript is a superset of JavaScript: it keeps all of JavaScript's syntax and adds its own on top. The additions are mostly type annotations (a colon and a type after a name) and type declarations such as interface. Everything else, from loops to objects to async functions, is plain JavaScript and is explained in the JavaScript topic.

interface MeterReading {
  meterId: string;
  kWh: number;
}

function totalKWh(readings: MeterReading[]): number {
  return readings.reduce((sum, r) => sum + r.kWh, 0);
}

const week: MeterReading[] = [
  { meterId: "E-1001", kWh: 11.2 },
  { meterId: "E-1001", kWh: 9.8 },
  { meterId: "E-1001", kWh: 12.5 },
];
console.log(`${week.length} readings, ${totalKWh(week).toFixed(1)} kWh`);
3 readings, 33.5 kWh

The interface describes the shape of a reading (see Objects, Interfaces and Type Aliases). readings: MeterReading[] says the parameter is an array of such readings, and : number after the parameter list says the function returns a number. Remove those annotations and the interface, and what is left is ordinary JavaScript that does exactly the same thing.

Why types help: errors before run time

JavaScript is dynamically typed: a variable can hold any value, and JavaScript quietly converts between types when an operator needs it. That makes some mistakes invisible. Here a reading arrives as text, and + joins strings instead of adding numbers:

function addReading(total, kWh) {
  return total + kWh;
}
console.log(addReading(10, "12.5"));
1012.5

No error, just a wrong number that may travel all the way to an invoice. The same function in TypeScript, with its parameters annotated, is refused before it can run:

function addReading(total: number, kWh: number): number {
  return total + kWh;
}
console.log(addReading(10, "12.5"));
example.ts(4,28): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.

The part of TypeScript that does this is the type checker: it reads the whole program, works out the type of every expression, and compares each use with what was declared. A mistake it finds is a compile-time error: an error reported while the code is being checked and compiled, before any of it has run. The message shows the file, the line and column ((4,28) points at "12.5"), an error code you can search for (TS2345), and a description. The opposite is a runtime error, which only appears when that line actually executes, perhaps for one customer in a thousand.

The checker catches more than wrong argument types. A misspelled property name is one of the most common bugs in JavaScript (it just gives undefined); in TypeScript it is an error with a suggestion:

const reading = { meterId: "E-1001", kWh: 4.2 };
console.log(reading.kwh.toFixed(2));
example.ts(2,21): error TS2551: Property 'kwh' does not exist on type '{ meterId: string; kWh: number; }'. Did you mean 'kWh'?

Notice that reading has no annotation at all. The checker worked out its type from the object literal; this is type inference, and it means you write far fewer types than you might expect (see Basic Types and Type Annotations).

Types also pay off in places that have nothing to do with bugs:

  • Editor help. Because the editor knows every type, it can complete property names, show a function's parameters while you type, and rename a function everywhere it is used.
  • Documentation that cannot go stale. A signature such as totalKWh(readings: MeterReading[]): number tells the next developer what goes in and what comes out, and the checker keeps it true.
  • Safer changes. Rename a property or add a required parameter, and the checker lists every place that must change. In a large code base that is the difference between a five-minute change and a risky one.

Types disappear when the code runs

No browser and no JavaScript engine runs TypeScript. Before the code can run, the type syntax has to be removed. The TypeScript compiler, tsc, does both jobs: it checks the types, and it emits JavaScript with the types taken out (see Setting Up: tsc, tsconfig.json and Running TypeScript).

meter.ts, which contains types and code, goes into tsc. tsc checks the types and reports type errors before anything runs; it also emits meter.js, which contains only code, and Node.js or a browser runs that file. meter.ts types + code tsc check, then emit meter.js code only type errors before anything runs Node.js or a browser
The checker and the code that runs never meet: types are used at compile time and are gone from the JavaScript that runs.

Here is a small file and the JavaScript that tsc emits for it. The program prints 1.34.

interface MeterReading { meterId: string; kWh: number; }
type Tariff = "day" | "night";
function cost(reading: MeterReading, tariff: Tariff): number {
  const price: number = tariff === "day" ? 0.32 : 0.25;
  return reading.kWh * price;
}
const r: MeterReading = { meterId: "E-1001", kWh: 4.2 };
console.log(cost(r, "day").toFixed(2));
function cost(reading, tariff) {
    const price = tariff === "day" ? 0.32 : 0.25;
    return reading.kWh * price;
}
const r = { meterId: "E-1001", kWh: 4.2 };
console.log(cost(r, "day").toFixed(2));

The interface and the type declaration are gone completely, and so is every : number and : MeterReading. The rest is your code, unchanged. (The real output also starts with two lines, "use strict"; and an Object.defineProperty(exports, …) line, because this file was compiled as a CommonJS module; they are left out here.) Removing types like this is called type erasure, the same word Java uses for its generics.

Erasure has consequences you need to keep in mind:

  • You cannot ask a type a question at run time. An interface is not a value, so instanceof MeterReading does not exist:
interface Ticket {
  id: string;
  priority: "P1" | "P2" | "P3";
}
const t: Ticket = { id: "INC-30412", priority: "P2" };
console.log(t instanceof Ticket);
example.ts(6,26): error TS2693: 'Ticket' only refers to a type, but is being used as a value here.
  • Types do not make code faster or slower. The engine runs the same JavaScript it would have run without them.
  • Types are not run-time checks. If a value from outside the program does not match its type, nothing stops it. The next example tells TypeScript that parsed JSON is a MeterReading with as; TypeScript believes it, and the reading that arrived as text gets glued to the 1, exactly as in plain JavaScript:
interface MeterReading {
  meterId: string;
  kWh: number;
}

// Text from an API: kWh arrives as a string, not a number
const body = '{"meterId": "E-1001", "kWh": "4.2"}';
const reading = JSON.parse(body) as MeterReading;

console.log(typeof reading.kWh);
console.log(reading.kWh + 1);
string
4.21

One more consequence surprises many people: by default, tsc still writes the JavaScript file when it has found type errors. The errors are reported and the exit code signals failure, but the output exists and runs, wrong number included:

npx tsc --ignoreConfig add-reading.ts
node add-reading.js
add-reading.ts:4:28 - error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.

4 console.log(addReading(10, "12.5"));
                             ~~~~~~

Found 1 error in add-reading.ts:4

1012.5

That is why a build pipeline must treat the type check as a gate (fail on errors), and why the option noEmitOnError exists. The examples on this site go one step further: an example with a type error is never run.

Gradual typing: as strict as you choose

TypeScript was designed to be adopted by existing JavaScript projects, so it allows gradual typing: typed and untyped code can live side by side, and you add types step by step. Three mechanisms make that possible:

  • The type any switches checking off for one value. It is an escape hatch, not a habit; its safer sibling unknown is explained in Basic Types and Type Annotations.
  • Compiler options decide how strict the checker is. Since TypeScript 6.0 the strict checks are on by default, which is what new projects should use (see Setting Up).
  • The checker can also read plain .js files, with types written in JSDoc comments, so a project can get type checking before a single file is renamed.

The checker is also structural: it compares shapes, not names. Any object with a meterId string and a kWh number is a MeterReading, whether or not anyone said so. That fits the way JavaScript code passes plain objects around, and it is the biggest difference from C# and Java.

What TypeScript does not do

Expectations shape how people use a tool, so it helps to be explicit about the limits:

Belief Reality
"It compiles, so it works." The checker proves that types fit together, not that the logic is right. A tariff of 0.23 instead of 0.32 is a valid number. You still need tests.
"API data has the type I declared." Only if your code checks it. Types are erased; see the warning above.
"TypeScript code runs faster." The JavaScript that runs is the same. Speed comes from the engine, not from the types.
"TypeScript is a different language from JavaScript." It is JavaScript with types. Run-time behavior, the standard library, this, promises and every quirk of type coercion are JavaScript's.
"Type annotations will soon be part of JavaScript." A TC39 proposal to let JavaScript engines ignore type syntax exists, but as of October 2026 it is still at Stage 1, with no progress since 2023 (see the proposal process).

Where TypeScript is used

You will meet TypeScript anywhere JavaScript runs, and in operations work you will often meet it without writing it:

  • Web front ends. Most large single-page applications are written in TypeScript; Angular projects use it by default, and React and Vue projects very often do. The code is compiled and bundled before it reaches the browser (see TypeScript in Node.js and the Browser).
  • Back-end services. APIs and background workers on Node.js, Deno or Bun, such as a service that collects meter readings or forwards alerts to a ticketing system.
  • Tools and editors. Visual Studio Code is written in TypeScript, as are many command-line tools, build tools and infrastructure-as-code projects. If you have looked at a project with a tsconfig.json file, you have seen one.
  • Libraries. Even libraries written in plain JavaScript usually ship type information, so TypeScript users get the same checking and editor help for them (see Modules, Declaration Files and Typing JavaScript Libraries).

Surveys agree that TypeScript is now mainstream. By GitHub's Octoverse 2025 count of monthly contributors, it became the most used language on GitHub in August 2025. In the Stack Overflow Developer Survey 2025, 43.6% of all respondents (48.8% of professional developers) said they used it, against 66% for JavaScript. Such numbers measure different things in different groups, so read them as a trend, not as exact market shares.

TypeScript 6, 7 and the native compiler

Until 2026 the TypeScript compiler was itself written in TypeScript and ran on Node.js. In March 2025 the TypeScript team announced a port to Go, to make builds and the editor experience much faster on large code bases. A native compiler is one compiled to machine code for the processor and operating system, instead of running as JavaScript inside Node.js; the Go version also checks several files in parallel.

Version Released What it means
TypeScript 5.9 Aug 2025 The last 5.x release; a much smaller tsc --init configuration.
TypeScript 6.0 Mar 2026 The last release of the compiler written in TypeScript. A bridge release: new defaults (strict mode on) and old options deprecated. No 6.1 is planned.
TypeScript 7.0 Jul 2026 The native compiler in Go, shipped as the normal typescript npm package with the same tsc command. Options deprecated in 6.0 are now errors.

As of October 2026, 7.0 is the current version (7.0.2 is the one used for the examples on this site). The TypeScript team reports full builds between 8 and 12 times faster than with 6.0. The language itself, the types you write, hardly changed in the move; what you notice are new defaults and removed options, covered in Setting Up.

How this topic is organized

The pages build on each other, and on the JavaScript topic for everything that happens at run time:

Every runnable example on these pages is type-checked with tsc in strict mode and then run on Node.js. Examples with a deliberate type error show the first error message instead of output, exactly as tsc prints it.