Anatomy of a TypeScript file
TypeScript is a strict syntactical superset of JavaScript that adds optional static typing, designed for development of large applications and transpiles to JavaScript.
File extensions: .ts
Every part of the example below is labelled and explained. This page is one of 55 annotated tours on AnatomyOf, a free, open-source project by LunarWerx Studios.
What is inside a TypeScript file
Comment
Single-line (//) or block (/* ... */), ignored by the compiler.
A block comment starts with /* and ends at the first */, and may span any number of lines in between; a single-line // comment is also available and runs to the end of the line. Both are stripped during compilation and have zero effect on the emitted JavaScript or on runtime behavior. Block comments cannot be nested, the first */ closes the comment even if another /* appears inside it. A /** ... */ doc comment placed directly above a declaration is picked up by editors as JSDoc, surfacing parameter hints and descriptions in autocomplete even though TypeScript itself ignores the tags for type-c
Interface definition
Defines the shape of an object, for static type checking.
An interface names a set of properties (and their types) that a value must have to satisfy it. It exists purely at compile time and is erased entirely from the emitted JavaScript. TypeScript uses structural typing: any object with a compatible shape satisfies Person, whether or not it was ever declared to implement it, unlike the nominal typing of languages such as Java. Interfaces can extend other interfaces (interface Employee extends Person), be reopened later in the same scope to add more members (declaration merging), and are generally preferred over type aliases for object shapes that a
Type annotation
Explicitly specifies the type of a variable, parameter, or return value (: Type).
A type annotation follows a colon after a name (name: string, age: number) and tells the compiler exactly what type is allowed there. The compiler checks every assignment and usage against the annotation and reports an error before the code ever runs, catching mismatches that would otherwise surface only as bugs in production JavaScript. Annotations are purely a compile-time construct: tsc strips every : Type when it emits JavaScript, so there is no runtime cost and no way to inspect a variable's declared type at runtime. This is what makes TypeScript a strict superset rather than a different
Class definition
Blueprint for objects, can implement interfaces (class ... implements ...).
class Employee implements Person declares a class whose instances must satisfy the Person interface, the compiler checks that every property Person requires is actually declared and initialized somewhere in Employee. A class can implement several interfaces at once, separated by commas, and can also extend exactly one base class to inherit its members. Unlike an interface, a class produces real runtime code: fields become properties on this, and methods are shared through the prototype chain exactly as in plain JavaScript. implements is checked only at compile time and leaves no trace in the e
Constructor
Special method for initializing objects; parameter properties can declare and assign fields.
The constructor runs once when a class is instantiated with new, receiving whatever arguments the call site provides. Each parameter is itself type-annotated, so passing the wrong argument types to new Employee(...) is a compile error rather than a runtime surprise. TypeScript also supports "parameter properties": prefixing a constructor parameter with public, private, readonly, or a combination automatically declares a field of that name and assigns it from the argument, without a separate declaration or an explicit this.x = x line. The verbose example spells the assignments out explicitly fo
Method definition
A function defined within a class.
A method is a function declared directly in a class body, such as greet(): string { ... }. Its return type is annotated after the parameter list, and the compiler verifies every return statement inside actually produces a value of that type. A mismatched or missing return is caught before the code runs. Inside a method, this refers to the instance the method was called on, same as in plain JavaScript, and TypeScript adds no special syntax for that binding. Methods can carry their own visibility modifiers (public, private, protected) to control whether they are callable from outside the class.
Template literal
String interpolation using backticks and interpolation placeholders.
A template literal is delimited by backticks instead of quotes, and any embedded interpolation placeholder is evaluated and converted to a string, then spliced into the result. This is identical to the JavaScript feature TypeScript compiles down to, template literals add no type-checking behavior of their own beyond checking that the interpolated expressions are well-typed. Template literals can also span multiple lines without escape sequences, unlike ordinary quoted strings. TypeScript separately offers "template literal types" (a type-level feature using the same backtick syntax) for buildi
Function definition
A standalone function with type annotations.
function logPerson(person: Person): void { ... } annotates both the parameter's type and the function's return type. void signals the function returns no usable value; calling it for its return value is a type error, though the function may still execute a return; with no expression. Because person is typed as Person, the compiler accepts any object with a compatible shape at the call site: an Employee instance qualifies automatically thanks to structural typing, with no explicit conversion or upcast needed. Optional parameters (age?: number) and default values (age: number = 0) can further re
Variable declaration
Declares variables (const/let); type can be explicit or inferred.
const and let behave exactly as they do in JavaScript (block-scoped, with const preventing reassignment of the binding) but TypeScript layers static typing on top. const employees: Employee[] = [...] explicitly annotates the array element type, so pushing anything other than an Employee into it is a compile error. An explicit annotation is not always necessary: TypeScript can often determine the type from the initializer alone, in which case adding one is redundant. Explicit annotations still earn their keep on empty arrays, function parameters, and public API boundaries, where there is no ini
Control flow (loop)
Executes code repeatedly (for...of, for, while).
for (const employee of employees) iterates the values of an array (or any iterable), and because employees is typed Employee[], the compiler already knows employee is an Employee inside the loop body. No manual cast is needed to call employee.greet(). for, while, and do...while are also available and behave exactly as in JavaScript. break exits the nearest loop and continue skips to the next iteration, identically to JavaScript. Iterating with for...in instead enumerates an object's keys as strings and is rarely used with typed arrays, since for...of already gives typed access to the elements
Type inference
The compiler automatically determines the type when not explicitly specified.
const message = "TypeScript is a superset of JavaScript." has no annotation, yet the compiler still infers message has the literal-widened type string from its initializer, and will flag any later attempt to assign a number to it. Inference also flows through function return types, array literals, and generic type arguments when they are not written explicitly. Under strict mode (the recommended baseline, enabled via "strict": true in tsconfig.json), inference becomes stricter still: variables with no initializer and no annotation are treated as implicitly any only if noImplicitAny is off, and
Generics
Parameterize a type, function, or class over another type (<T>).
A generic like function firstOf<T>(items: T[]): T introduces a type parameter T that is filled in per call site, firstOf(employees) infers T as Employee without it being written explicitly. This lets a single function, interface, or class stay fully type-safe while working over many different element types, instead of duplicating the logic per type or falling back to any. Generics can be constrained (<T extends Person>) to require the type argument satisfy some shape, and given defaults (<T = string>) for when no argument is supplied. Like all TypeScript types, generic parameters are erased at
Official TypeScript site · All languages on AnatomyOf
The interactive tour needs JavaScript. Enable it to hover a callout and trace it into the code.