TypeScript · Classes

Classes

TypeScript classes are JavaScript classes plus types — and a few time-saving extras like parameter properties. If you know C# or Java, this will feel familiar.

Intermediate 5 min Lesson 15 of 29Examples target TypeScript 5.x with "strict": true.
0/29 in TypeScript
On this page · 5 min · Intermediate

Learning objectives#

  • Declare typed properties and constructors
  • Use parameter properties to cut boilerplate
  • Add readonly fields, getters and setters
  • Implement interfaces in classes

Explanation#

Class properties must be declared with their types: name: string;. Under strict mode, every property must be initialised in the declaration or the constructor.

Parameter properties: constructor(private name: string) declares and assigns the property in one step. This shorthand is very common in Angular services.

readonly properties can be set only in the declaration or the constructor.

get and set accessors can validate values; TypeScript types them like properties.

implements InterfaceName makes the compiler check the class against a contract.

Syntax#

TypeScript Illustrative
class User {
  constructor(public readonly id: number, public name: string) {}
  greet(): string { return `Hi ${this.name}`; }
}

Code example: A typed product class#

TypeScriptA typed product class Illustrative
interface Discountable {
  applyDiscount(percent: number): void;
}


class Product implements Discountable {
  private _price: number;
  readonly createdAt = new Date();


  constructor(
    public readonly id: number,
    public name: string,
    price: number,
  ) {
    this._price = price;
  }


  get price(): number {
    return this._price;
  }
  set price(value: number) {
    if (value < 0) throw new Error('Price cannot be negative');
    this._price = value;
  }


  applyDiscount(percent: number): void {
    this.price = Math.round(this._price * (1 - percent / 100));
  }
}


const p = new Product(1, 'Headphones', 2000);
p.applyDiscount(10);
console.log(p.name, p.price);   // Headphones 1800
p.id = 5;                        // ✗ Cannot assign to 'id' because it is a read-only property
p._price = 0;                    // ✗ Property '_price' is private and only accessible within class 'Product'
new Product(2, 'Mouse');         // ✗ Expected 3 arguments, but got 2
Expected output
Headphones 1800 — and three compile errors for changing the readonly id, touching the private field and calling the constructor with a missing argument.

This example is illustrative. Copy or download it and run it in your own environment; the expected output is shown above.

Step-by-step explanation#

  1. Product promises to implement Discountable.
  2. public readonly id and public name are parameter properties — declared and assigned automatically.
  3. price is a normal parameter assigned to the private _price.
  4. The price getter/setter validates new values.
  5. applyDiscount uses the setter, so validation always runs.
  6. TypeScript blocks writes to readonly/private members and wrong constructor calls.

Real-world use case#

Angular components and services, NestJS controllers and domain models (Order, Invoice) are TypeScript classes with typed members.

Common mistakes#

Property not initialised

Under strict mode, 'name' has no initializer and is not definitely assigned in the constructor. Assign it, give a default, or make it optional.

Forgetting the modifier in parameter properties

constructor(name: string) does not create a property. You need public, private, protected or readonly in front.

Losing this in callbacks

Passing obj.method as a callback loses this. Use arrow-function properties or bind.

Best practices#

  • Use parameter properties for simple constructors
  • Mark ids and creation data readonly
  • Keep fields private and expose behaviour through methods
  • Implement interfaces so classes are swappable in tests

Remember this#

constructor(private x: T) = declare + assign in one go.

readonly = set once, then frozen.

implements = the compiler checks the contract for you.

Practice exercise#

Your task: Write a class BankAccount with a readonly accountNumber, a private balance starting at 0, deposit(amount) and a balance getter. Reject negative deposits.

Need a hint?
Use a parameter property for accountNumber.
Show solution
TypeScript Illustrative
class BankAccount {
  private _balance = 0;
  constructor(public readonly accountNumber: string) {}


  deposit(amount: number): void {
    if (amount <= 0) throw new Error('Deposit must be positive');
    this._balance += amount;
  }
  get balance(): number {
    return this._balance;
  }
}

Mini quiz#

Classes quizMultiple choice Question 1 of 3

What does constructor(private name: string) {} do?

Score so far: 0/0

Want more? Practise all TypeScript MCQs · TypeScript interview questions

My notes#

Saved in this browser.

Progress is saved in this browser. Sign in to sync.