TypeScript Classes Tutorial with Examples

In object-oriented programming languages like Java and C#, classes are the fundamental entities used to create reusable components.
The syntax of creating classes in TypeScript should look familiar if you’ve used C# or Java before.
Note: To run or execute source code examples of this tutorial, follow How to Run the TypeScript Code guide.

Table of contents 

  • TypeScript Class Example
  • TypeScript constructor
  • Creating an Object of Class
  • Inheritance in TypeScript
  • Public, private, and protected modifiers
  • Readonly modifier
  • Accessors - getters/setters
  • Static Properties
  • Abstract Classes 

TypeScript Simple Class Example

Let's create a simple Employee class with the following members:
  • id
  • firstName
  • lastName
  • getFullName()
class Employee {
    id: number;
    firstName: string;
    lastName: string;

    constructor(id: number, firstName: string, lastName: string) {
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
    }

    getFullName() {
        return this.firstName + ' ' + this.lastName;
    }
}

// create Employee class object
let employee = new Employee(100, 'Ramesh', 'Fadatare');
console.log(employee);
console.log(employee.getFullName());
Output:
Employee { id: 100, firstName: 'Ramesh', lastName: 'Fadatare' }
Ramesh Fadatare
The TypeScript compiler will convert the above class to the following JavaScript code using closure:
"use strict";
exports.__esModule = true;
var Employee = /** @class */ (function () {
    function Employee(id, firstName, lastName) {
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
    }
    Employee.prototype.getFullName = function () {
        return this.firstName + this.lastName;
    };
    return Employee;
}());
exports.Employee = Employee;
// create Employee class object
var employee = new Employee(100, 'Ramesh', 'Fadatare');
console.log(employee);
console.log(employee.getFullName());

Constructor

The constructor is a special type of method which is called when creating an object. In TypeScript, the constructor method is always defined with the name "constructor".

Example: Constructor

class Employee {
    id: number;
    firstName: string;
    lastName: string;

    constructor(id: number, firstName: string, lastName: string) {
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
    }
}
In the above example, the Employee class includes a constructor with the parameters id, firstName, and lastName. In the constructor, members of the class can be accessed using this keyword e.g. this.firstName or this.lastName.
It is not necessary for a class to have a constructor.
class Employee{
    id: number;
    firstName: string;
    lastName: string;

    getFullName(){
        return this.firstName + ' ' + this.lastName;
    }
}

// create Employee class object
let employee = new Employee();
employee.id = 100;
employee.firstName = 'Ramesh';
employee.lastName = 'Fadatare';

console.log(employee);
console.log(employee.getFullName());
Output:
Employee { id: 100, firstName: 'Ramesh', lastName: 'Fadatare' }
Ramesh Fadatare

Creating an Object of Class

An object of the class can be created using the new keyword.

Example: Create an Object

class Employee{
    id: number;
    firstName: string;
    lastName: string;
}

// create Employee class object
let employee = new Employee();

employee.id = 100;
employee.firstName = 'Ramesh';
employee.lastName = 'Fadatare';

console.log(employee);
Let's create a parameterized constructor example:
class Employee{
    id: number;
    firstName: string;
    lastName: string;

    constructor(id: number, firstName: string, lastName: string){
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
    }

    getFullName(){
        return this.firstName + ' ' + this.lastName;
    }
}

// create Employee class object
let employee = new Employee(100, 'Ramesh', 'Fadatare');
console.log(employee);
console.log(employee.getFullName());

Inheritance

Just like object-oriented languages such as Java and C#, TypeScript classes can be extended to create new classes with inheritance, using the keyword extends.
class Animal {
    move(distanceInMeters: number = 0) {
        console.log(`Animal moved ${distanceInMeters}m.`);
    }
}

class Dog extends Animal {
    bark() {
        console.log('Woof! Woof!');
    }
}

const dog = new Dog();
dog.bark();
dog.move(10);
dog.bark();
This example shows the most basic inheritance feature: classes inherit properties and methods from base classes. Here, Dog is a derived class that derives from the Animal base class using the extends keyword. Derived classes are often called subclasses, and base classes are often called superclasses.
Because Dog extends the functionality from Animal, we were able to create an instance of Dog that could both bark() and move().
Let’s now look at a more complex example.
class Animal {
    name: string;
    constructor(theName: string) { this.name = theName; }
    move(distanceInMeters: number = 0) {
        console.log(`${this.name} moved ${distanceInMeters}m.`);
    }
}

class Snake extends Animal {
    constructor(name: string) { super(name); }
    move(distanceInMeters = 5) {
        console.log("Slithering...");
        super.move(distanceInMeters);
    }
}

class Horse extends Animal {
    constructor(name: string) { super(name); }
    move(distanceInMeters = 45) {
        console.log("Galloping...");
        super.move(distanceInMeters);
    }
}

let sam = new Snake("Sammy the Python");
let tom: Animal = new Horse("Tommy the Palomino");

sam.move();
tom.move(34);
This example covers a few other features we didn’t previously mention. Again, we see the extends keywords used to create two new subclasses of Animal: Horse and Snake.

Public, private, and protected modifiers

Public by default

In TypeScript, each member is public by default. If you’re familiar with classes in other languages like Java, you may have noticed in the above examples we haven’t had to use the word public to accomplish this; for instance, Java requires that each member is explicitly labeled public to be visible.
You may still mark a member public explicitly. For example:
class Employee {
    public id: number;
    public firstName: string;
    public lastName: string;

    constructor(id: number, firstName: string, lastName: string) {
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
    }

    public getFullName() {
        return this.firstName + ' ' + this.lastName;
    }
}

// create Employee class object
let employee = new Employee(100, 'Ramesh', 'Fadatare');
console.log(employee);
console.log(employee.getFullName());
Output:
Employee { id: 100, firstName: 'Ramesh', lastName: 'Fadatare' }
Ramesh Fadatare
After compiling, the above TypeScript code produces below JavaScript code:
var Employee = /** @class */ (function () {
    function Employee(id, firstName, lastName) {
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
    }
    Employee.prototype.getFullName = function () {
        return this.firstName + ' ' + this.lastName;
    };
    return Employee;
}());
// create Employee class object
var employee = new Employee(100, 'Ramesh', 'Fadatare');
console.log(employee);
console.log(employee.getFullName())

Understanding private

When a member is marked private, it cannot be accessed from outside of its containing class. For example:
class Employee {
    private id: number;
    public firstName: string;
    public lastName: string;

    public getFullName() {
        return this.firstName + ' ' + this.lastName;
    }
}

// create Employee class object
let employee = new Employee();
employee.id = 100; // Property 'id' is private and only accessible within class 'Employee'.ts
employee.firstName = 'Ramesh';

console.log(employee);
console.log(employee.getFullName());
Above code gives below compilation error:
Property 'id' is private and only accessible within class 'Employee'.ts

Understanding protected

The protected modifier acts much like the private modifier with the exception that members declared protected can also be accessed within deriving classes. For example,
class Person {
    protected name: string;
    constructor(name: string) {
        this.name = name;
    }
}

class Employee extends Person {
    private department: string;

    constructor(name: string, department: string) {
        super(name);
        this.department = department;
    }

    public getElevatorPitch() {
        return `Hello, my name is ${this.name} and I work in ${this.department}.`;
    }
}

let howard = new Employee("Howard", "Sales");
console.log(howard.getElevatorPitch());
console.log(howard.name); // Property 'name' is protected and only 
                          // accessible within class 'Person' and its subclasses.
Notice that while we can’t use name from outside of Person, we can still use it from within an instance method of Employee because Employee derives from Person. Above code gives below compilation error:
Property 'name' is protected and only accessible within class 'Person' and its subclasses.
A constructor may also be marked protected. This means that the class cannot be instantiated outside of its containing class, but can be extended. 
For example,
class Person {
    protected name: string;
    protected constructor(theName: string) { this.name = theName; }
}

// Employee can extend Person
class Employee extends Person {
    private department: string;

    constructor(name: string, department: string) {
        super(name);
        this.department = department;
    }

    public getElevatorPitch() {
        return `Hello, my name is ${this.name} and I work in ${this.department}.`;
    }
}

let howard = new Employee("Howard", "Sales");
let john = new Person("John"); // Error: The 'Person' constructor is protected

Readonly modifier

You can make properties readonly by using the readonly keyword. Readonly properties must be initialized at their declaration or in the constructor. 
For Example:
class Employee{
    readonly id: number;
    public firstName: string;
    readonly lastName: string;

    constructor(id: number, firstName: string, lastName: string){
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
    }

    public getFullName(){
        return this.firstName + ' ' + this.lastName;
    }
}

// create Employee class object
let employee = new Employee(100, 'Ramesh', 'Fadatare');
employee.id = 200; // Error: Cannot assign to 'id' because it is a read-only property.
employee.lastName = 'Kapoor'; // Error: Cannot assign to 'lastName' because it is a read-only property
console.log(employee);
console.log(employee.getFullName());
Notice that the above code gives below compilation error:
employee.id = 200; // Error: Cannot assign to 'id' because it is a read-only property.
employee.lastName = 'Kapoor'; // Error: Cannot assign to 'lastName' because it is a read-only property

Accessors - getters/setters

TypeScript supports getters/setters as a way of intercepting accesses to a member of an object. This gives you a way of having finer-grained control over how a member is accessed on each object.
Let’s convert a simple class to use get and set.
class Employee {
    private _id: number;
    private _fullName: string;

    public get id(): number {
        return this._id;
    }
    public set id(value: number) {
        this._id = value;
    }

    public get fullName(): string {
        return this._fullName;
    }
    public set fullName(value: string) {
        this._fullName = value;
    }
}

// create Employee class object
let employee = new Employee();
employee.id = 200;
employee.fullName = 'Ramesh Fadatare';
console.log(employee);
console.log(employee.fullName);
Output:
Employee { _id: 200, _fullName: 'Ramesh Fadatare' }
Ramesh Fadatare
The TypeScript compiler will convert the above class to the following JavaScript code using closure:
var Employee = /** @class */ (function () {
    function Employee() {
    }
    Object.defineProperty(Employee.prototype, "id", {
        get: function () {
            return this._id;
        },
        set: function (value) {
            this._id = value;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(Employee.prototype, "fullName", {
        get: function () {
            return this._fullName;
        },
        set: function (value) {
            this._fullName = value;
        },
        enumerable: true,
        configurable: true
    });
    return Employee;
}());
// create Employee class object
var employee = new Employee();
employee.id = 200;
employee.fullName = 'Ramesh Fadatare';
console.log(employee);
console.log(employee.fullName);

Static Properties

TypeScript allows creating static members of a class, those that are visible on the class itself rather than on the instances. Static members are referenced by the class name.
In below example, we have two static class members, one is static property and another static method:
class Employee{
    static fullName: string;

    static getFullName(){
        return Employee.fullName;
    }
}

// create Employee class object
Employee.fullName = 'Ramesh Fadatare';
console.log(Employee.getFullName());
Output:
Ramesh Fadatare

Abstract Classes

Abstract classes are base classes from which other classes may be derived. They may not be instantiated directly. Unlike an interface, an abstract class may contain implementation details for its members. The abstract keyword is used to define abstract classes as well as abstract methods within an abstract class.
abstract class Employee {

    name: string;
    paymentPerHour: number;

    constructor(name: string, paymentPerHour: number) {
        this.name = name;
        this.paymentPerHour = paymentPerHour;
    }

    public abstract calculateSalary(): number;
}

class Contractor extends Employee {

    workingHours: number;
    constructor(name: string, paymentPerHour: number, workingHours: number) {
        super(name, paymentPerHour);
        this.workingHours = workingHours;
    }

    calculateSalary(): number {
        return this.paymentPerHour * this.workingHours;
    }
}

class FullTimeEmployee extends Employee {
    constructor(name: string, paymentPerHour: number) {
        super(name, paymentPerHour);
    }

    calculateSalary(): number {
        return this.paymentPerHour * 8;
    }
}


let contractor: Employee;
let fullTimeEmployee: Employee;
contractor = new Contractor('Ramesh contractor', 10, 5);
fullTimeEmployee = new FullTimeEmployee('Ramesh full time employee', 8);

console.log(contractor.calculateSalary());
console.log(fullTimeEmployee.calculateSalary());
Output:
50
64
Learn more about TypeScript at TypeScript Tutorial with Examples.

Comments