Classes

By the end of this lesson you'll design your own classes in TypeScript — with typed fields, constructors, access modifiers, getters/setters, interfaces, and inheritance — the toolkit behind every real-world TypeScript app.

Learn Python, JavaScript, Java and more with free interactive lessons, real projects and AI-powered help. Beginner-friendly.

Part of the free TypeScript course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

1. Classes, Fields & the Constructor

A class is a blueprint for objects. The constructor is a special method that runs once when you write new ClassName(...) ; its job is to store the starting values on this — the brand-new object being built. A method is just a function that lives on the object. Read this worked example, run it, then you'll write your own.

In TypeScript you add a type to every field and parameter, so the compiler catches mistakes before the code runs. You declare the fields above the constructor with name: string . TypeScript also offers a shortcut called parameter properties : put an access modifier on a constructor parameter and TypeScript declares the field and assigns it for you — no this.name = name boilerplate. (This block is read-only; it's TypeScript-specific syntax.)

2. Access Modifiers & readonly

Modifiers decide who can touch a field . public (the default) is readable everywhere; private is reachable only inside the same class; protected adds subclasses to that circle; and readonly lets a field be set once (in the constructor) and then locks it. These checks are TypeScript-only — they protect you while you type, then vanish at runtime — so this is a read-only block.

3. Getters & Setters

A getter looks like a plain property when you read it ( temp.fahrenheit , no parentheses) but actually runs code — great for values you want to compute on the fly. A setter runs when you assign ( temp.celsius = 30 ), which is the perfect place to validate. By convention the backing field is named with a leading underscore, like _celsius .

Your turn. The Book class below is almost finished — fill in the five blanks marked ___ using the // 👉 hints, then run it and check your output.

4. Inheritance: extends & super

extends says "this class is a kind of that one" and inherits its fields and methods. Inside a subclass constructor you must call super(...) first — that runs the parent's constructor before you touch this . A subclass can override a method by redefining it; each object then uses its own version. Read the worked example, then complete the exercise below it.

Now you try. Make Dog inherit from Animal , call super in its constructor, and override speak() . Fill in the four blanks:

5. Implementing an Interface

An interface is a contract : a list of methods and properties a class promises to provide. Writing class Product implements Comparable tells TypeScript "check that Product has everything Comparable requires." If a method is missing you get error TS2420 at compile time, long before users hit it. A class can implement several interfaces at once. Here's the TypeScript contract, then a runnable class that fulfils it:

Just like functions, a class can take a type parameter written in angle brackets, conventionally T . That lets one class work with any type while staying fully type-safe — a Box number only ever holds numbers, a Box string only strings, with no casting and no any .

You'll meet this constantly in real code: Array T , Map K, V , and Promise T are all generic classes from the standard library.

Q: What's the difference between a class and an interface?

A class is real code you can new to build objects; it has fields and method bodies. An interface is only a type-checking contract — a list of what must exist, with no implementation. A class can implements an interface to prove it satisfies that contract.

Q: When should I use parameter properties vs declaring fields normally?

Use parameter properties when the constructor just stores its arguments — it removes the repetitive this.x = x lines. Declare fields the long way when a field isn't a direct constructor argument, or when it needs extra setup.

Q: Is TypeScript's private truly hidden at runtime?

No. private is enforced only by the compiler; the compiled JavaScript still exposes the field. For privacy that survives at runtime, use a native private field with a # prefix, like #balance .

Q: Why must I call super() before using this in a subclass?

Because the parent's constructor is what actually sets up the object's inherited fields. Until super() runs, this isn't fully built, so JavaScript forbids touching it.

No blanks this time — just a brief and an outline. Write the Stack class yourself (a "last in, first out" list), then uncomment the test lines and check your output against the expected lines. This is the kind of small, reusable class real apps are full of.

Practice quiz

What is the job of a class constructor?

  • To define the class name
  • To delete the object
  • To run once on new ClassName(...) and set up the new object on this
  • To import dependencies

Answer: To run once on new ClassName(...) and set up the new object on this. The constructor runs once when you write new ClassName(...); its job is to store starting values on this, the new object.

What does a parameter property like constructor(public name: string) do?

  • Declares the field AND assigns it in one line
  • Makes the parameter optional
  • Marks the constructor as public
  • Creates a getter

Answer: Declares the field AND assigns it in one line. Putting an access modifier on a constructor parameter declares the field and assigns it automatically - no this.name = name needed.

Which access modifier limits a field to only inside the same class?

  • public
  • protected
  • readonly
  • private

Answer: private. private restricts a field to the class itself. protected also allows subclasses; public is accessible everywhere.

What does protected add compared to private?

  • Access from anywhere
  • Access from this class AND its subclasses
  • Runtime immutability
  • Nothing - they are identical

Answer: Access from this class AND its subclasses. protected widens private's circle to include subclasses, but still blocks access from outside the class hierarchy.

Where can a readonly field be assigned?

  • Only in the constructor, then it's locked
  • Anywhere in the class
  • Only outside the class
  • Never

Answer: Only in the constructor, then it's locked. A readonly field can be set once - in the constructor - and is then frozen; later assignment is a compile error (TS2540).

Is TypeScript's private modifier enforced at runtime?

  • Yes, the field is hidden in compiled JavaScript
  • Only in strict mode
  • No - it's a compile-time check only; use #field for runtime privacy
  • Only for methods

Answer: No - it's a compile-time check only; use #field for runtime privacy. private is compile-time only; the compiled JS still exposes the field. Use a native #field for privacy JavaScript enforces.

How is a getter accessed?

  • Like a method call: temp.fahrenheit()
  • Like a plain property, with no parentheses: temp.fahrenheit
  • With the get keyword each time
  • Only via a setter

Answer: Like a plain property, with no parentheses: temp.fahrenheit. A getter looks like a property when read - temp.fahrenheit with no parentheses - but actually runs code behind the scenes.

In a subclass constructor, what must you do before accessing this?

  • Declare all fields
  • Return a value
  • Call the method being overridden
  • Call super(...) first

Answer: Call super(...) first. You must call super(...) before touching this, because the parent's constructor sets up the inherited part of the object.

What does class Product implements Comparable tell TypeScript?

  • Product inherits Comparable's code
  • Product must provide every member Comparable requires, checked at compile time
  • Comparable becomes a subclass of Product
  • Product is converted to an interface

Answer: Product must provide every member Comparable requires, checked at compile time. implements is a contract: TypeScript verifies the class supplies every member the interface lists, erroring with TS2420 if not.

What does a generic class Box<T> give you?

  • A box that holds only strings
  • A class with no fields
  • One class that works with any type while staying type-safe
  • A runtime type check

Answer: One class that works with any type while staying type-safe. A type parameter <T> lets one class work with any type safely - a Box<number> only holds numbers, a Box<string> only strings.