012 — Classes (blueprint, constructor, instances, format)
Full companion narrative for TypeScript Tutorial #12 — Classes: the Invoice blueprint, constructor assignment, instances with new, the format() method, and Invoice[] collections
Video: 012 · TypeScript Tutorial #12 - Classes · watch · ~7 min · Net Ninja TypeScript tutorial series, module 05 (objects and interfaces)
Source: this is a written companion to the video. Part of the Favorite TypeScript Videos curated path, module 05 (objects and interfaces). The first classes lesson: a class bundles data plus behavior into one blueprint, and instances stamped from it share the structure with their own data.
a blueprint holding data plus behavior
A class is a blueprint. It declares the shape of an object (properties with types) and the things it can do (methods) in one place. You then stamp out instances with new, each holding its own data but sharing the same structure. In this video the blueprint is an Invoice with a client name, details, and an amount, built inside the ongoing Finance Logger app.

The app opens on the familiar form — Type, To/From, Details, Amount — with an empty list. The invoices this lesson creates will land there.
typed properties up front
A class names its properties and types them up front, using the same annotation syntax as variables:
class Invoice {
client: string;
details: string;
amount: number;
constructor(c: string, d: string, a: number) {
this.client = c;
this.details = d;
this.amount = a;
}
}

The client and details parameters are typed string, while amount is number — the types sit on the constructor parameters exactly as they would on standalone variable declarations.
the constructor copies arguments onto the instance
The constructor runs once per new. It takes the incoming arguments and copies them onto the instance via this:
constructor(c: string, d: string, a: number) {
this.client = c; // parameter c -> field client
this.details = d; // parameter d -> field details
this.amount = a; // parameter a -> field amount
}
stamping out instances with new
Three arguments, one per constructor parameter, in order. Each new produces an independent object:
const invOne = new Invoice("mario", "work on the mario website", 250);
const invTwo = new Invoice("luigi", "work on the luigi website", 300);
console.log(invOne, invTwo);
The console confirms two distinct Invoice objects, each carrying its own client, details, and amount.




the format() method
Methods live inside the class and use this to read the instance’s own fields. Here format() returns a human-readable summary string, interpolating the instance’s variables into a template literal:
class Invoice {
client: string;
details: string;
amount: number;
constructor(c: string, d: string, a: number) {
this.client = c;
this.details = d;
this.amount = a;
}
format() {
return `${this.client} owes £${this.amount} for ${this.details}`;
}
}
console.log(invOne.format());
console.log(invTwo.format());


the class name as a type for collections
Once the class exists it becomes a usable type. An array meant to hold only invoices is typed Invoice[], so pushing anything else is a compile error:
const invoices: Invoice[] = [];
invoices.push(invOne);
invoices.push(invTwo);
// invoices.push('hello'); // ERROR: Argument of type 'string' is not assignable to parameter of type 'Invoice'
The class name doing double duty — blueprint at new time, type at annotation time — is the idea the rest of the module builds on.
The outro points at access control — who gets to read or change each property — 013 — Classes: public, private, readonly.
Prev: 011 — The DOM & Type Casting · Next: 013 — Access Modifiers
Transcript notes: constructor params c, d, a; client/details typed string; template-literal interpolation in format(); the collection annotated Invoice[]; src/app.ts. Currency glyph varies across frames (£ vs Euro) — an OCR artifact; amount stays number. Modifiers, modules, and interfaces follow next.