TypeScript

On this page 7

TypeScript is an open source programming language that extends JavaScript with optional static typing and compiles to plain JavaScript. Among programming languages, it is a typed superset of JavaScript: every valid JavaScript program is, with minor exceptions, also valid TypeScript, while TypeScript adds type annotations, interfaces, generics and other features that a compiler checks before the code runs.

TypeScript was released by Microsoft in 2012 and has become a common choice for large web front ends, Node.js services, desktop applications built with web technologies and tooling. Its value lies less in new runtime capabilities, since the output is ordinary JavaScript, than in finding errors early and making large codebases easier to understand and change.

How TypeScript works

TypeScript code is processed by the TypeScript compiler, tsc, or by a faster tool that only strips types. The compiler performs two separate jobs: type checking, which analyzes the code and reports errors, and emitting JavaScript, which removes type annotations and optionally converts newer syntax for older environments.

The key design principle is type erasure. Types exist only at compile time and leave no trace in the generated JavaScript. A function declared with a parameter of type number therefore performs no runtime check; if external data such as a network response has the wrong shape, the program fails only when the code uses it, unless the developer adds runtime validation explicitly.

TypeScript uses structural typing: two types are compatible if they have compatible shapes, regardless of their names. An object with the properties name and email satisfies any interface that requires those properties. This matches the way JavaScript code is written in practice, but it differs from the nominal typing of Java or C#, where types must be declared as related.

Core language features

TypeScript’s type system is unusually expressive, because it must describe the dynamic patterns common in existing JavaScript. The table lists the features developers use most often.

FeatureExampleWhat it achieves
Type annotationlet count: numberDeclares the expected type
Type inferencelet count = 0Derives types without annotations
Interface and type aliasinterface User { id: string }Names the shape of objects
Union typestring | nullAllows one of several types
Genericsfunction first<T>(items: T[])Reusable code for many types
Narrowingif (typeof x === "string")Refines a type after a check
Utility typesPartial<User>, Readonly<User>Transforms existing types
Frequently used TypeScript features

Declaration files with the .d.ts extension describe the types of existing JavaScript libraries. They allow typed use of untyped code and are distributed either with the library itself or through community-maintained type packages.

TypeScript compared with neighboring languages

TypeScript is most often weighed against plain JavaScript, but comparisons with other statically typed languages clarify what its type system can and cannot promise.

LanguageTypingRuntime type safetyTypical domain
TypeScriptStatic, structural, gradualNo, types are erasedWeb front ends, Node.js, tooling
JavaScriptDynamicOnly runtime type errorsBrowsers, Node.js, scripting
JavaStatic, nominalYes, enforced by the virtual machineEnterprise back ends, Android
Python with type hintsGradual, checked by external toolsNo, hints are not enforcedScripting, data, back ends
RustStatic, nominal, strictYes, with memory safetySystems, performance-critical code
TypeScript and related languages

The type system is intentionally unsound in some places, for example around array indexing and certain function parameter rules, to remain practical for real JavaScript. Developers should treat TypeScript as a strong safety net, not as a mathematical guarantee.

Configuration and adoption

A project’s behavior is controlled by the tsconfig.json file. Its options decide how strict the checks are, which JavaScript version is produced and how modules are resolved. The most important settings are summarized below.

OptionEffectRecommended setting
strictEnables the full set of strict checksOn for new projects
noImplicitAnyRejects values with an unknown typeOn, part of strict
strictNullChecksTreats null and undefined as separate typesOn, part of strict
targetJavaScript version of the outputMatch the oldest supported runtime
module and moduleResolutionModule system and lookup rulesMatch the bundler or Node.js setup
allowJsMixes JavaScript files into the projectOn during gradual migration
Key compiler options

Existing JavaScript projects are usually migrated incrementally: TypeScript is added with allowJs, files are renamed one by one, and strictness is raised over time. Some runtimes can now execute TypeScript files directly by stripping types, and a native port of the compiler announced in 2025 aims at much faster type checking on large codebases.

Limitations and common mistakes

Most problems in TypeScript projects come from trusting types more than the data, or from weakening the type system to silence errors.

  • Overusing the any type turns off checking and spreads silently through the code; the unknown type is a safer alternative.
  • Skipping runtime validation of external input, such as API responses or form data, because types disappear at runtime.
  • Excessive type assertions, such as value as User, which tell the compiler to trust the developer without proof.
  • Overly complex types that slow the compiler and are hard for colleagues to read.
  • Version drift between the compiler, type packages and libraries, causing confusing errors after upgrades.

Understanding it simply

TypeScript is JavaScript with labels on the data. A programmer writes which kind of information each part of the program expects. Examples are a number, a piece of text or a customer record. A checking tool then reads the whole program before it runs.

If something does not fit, such as text where a number belongs, the tool points out the mistake right away. It is like a spelling checker for program logic. The finished program is still plain JavaScript, so it runs anywhere JavaScript runs.

Applied in practice

A team of eight developers maintains a booking web application with about 120,000 lines of JavaScript. Renaming a field in the customer object regularly broke screens nobody had tested, and these errors appeared only in production.

The team adds TypeScript with allowJs enabled and converts the shared data models first, then the most frequently changed screens. Over six months, they turn on strict mode module by module and add runtime validation for responses from the booking API. When a developer later renames the phoneNumber field, the compiler lists every one of the 37 places that must change before the code can be merged. The outcome is renaming and refactoring without fear, and a sharp drop in errors that first appear in front of customers.