Start learning free

LESSON 176 OF 348 · FUNCTIONS & CLASSES

Classes in TypeScript: Properties, Constructors and Methods

Lesson Read the full explanation

JavaScript is an object oriented programming language. Almost everything in JS is an object, with its attributes and methods.

Class creates a user-defined data structure, which holds its own data members (attributes) and member functions (methods), which can be accessed and used by creating an instance of that class.

Classes are like a blueprint for objects outlining possible behaviors and states that every object of a certain type could have.

Classes are defined via the keyword class. We should always add a method named constructor(), we'll see why later.

// Define an empty class Employee
class Employee {
	constructor() {}
};

Objects/Instances

An Object is an instance of a Class. A class is like a blueprint while an instance is a copy of the class with actual values. It’s not an idea anymore, it’s an actual employee, like a person named "Andrew" who is 30 years old.

You can have many employees to create many different instances, but without the class as a guide, you would be lost, not knowing what information is required.

After a class is defined, we can create objects of the class using the new keyword like this:

// Define an empty class Employee
class Employee {
	constructor() {}
};

let employee = new Employee();

Attributes/Properties

A class attribute is a JavaScript variable that belongs to a class and is shared between all the objects of this class. Let's add some attributes to our Employee class:

class Employee {
	constructor(name, age) {
		this.name = name;
		this.age = age;
	}
};

let emp = new Employee('Andrew', 30);
	
console.log(emp.name); // prints 'Andrew'
	
emp.age = 40;

console.log(emp.age); // prints 40

We added two properties: the string name and the number age.

Now you can see why constructor() is so important: it is a special method for creating and initializing the attributes within an object.

The attributes of objects can be accessed and modified using the dot operator (.), like we did above with emp.name and emp.age.

The "this"

Every object in JavaScript has access to its own address through an important refference called this.

The this refference is an implicit parameter to all member functions. Therefore, inside a member function, this may be used to access and manipulate the attributes of that object, like we did above with this.name = name.

Member functions

Member functions are functions that belong to the class:

class Employee {
	constructor(name, age) {
		this.name = name;
		this.age = age;
	}
	
	// member functions:
	printName() {
		console.log(this.name);
	}
		
	printEmployee() {
		this.printName();
		console.log(this.age);
	}
};

let emp1 = new Employee('Andrew', 30);
	
emp1.printEmployee(); // prints 'Andrew', 30

let emp2 = new Employee('Mary', 25);
	
emp2.printEmployee(); // prints 'Mary', 25

As you can see, we access functions just like we access attributes: using the dot syntax (.).

The function call uses the attributes of the object it was called on. That's why the first printEmployee() prints 'Andrew' and 30 and the second prints 'Mary' and 25.

One more important thing to know is that when we call a member function from an other member function, we should use the this keyword like we did above: this.printName();

Rewriting classes as pure methods

Throught the tutorials you will notice that we don't use the class syntax. This is because a class can be also written as a function:

function Employee(name, age) {
	this.name = name;
	this.age = age;
	this.printName = function() {
		console.log(this.name);
	};
	this.printEmployee = function() {
		this.printName();
		console.log(this.age);
	};
}

let emp = new Employee('Andrew', 30);
emp.printEmployee();

Assignment
Follow the Coding Tutorial and let's write some classes.


Hint
Look at the examples above if you get stuck.


STEP 1 OF 7
    Ctrl + Enter to check

    TYPESCRIPT · FUNCTIONS & CLASSES

    Classes in TypeScript, explained

    What a class is

    A class is a blueprint for objects. It says which data each object carries, called its properties, and which actions it can perform, called its methods. An object made from the class is an instance. The class Employee describes what any employee has, such as a name and an age, while one instance is the actual employee named Andrew who is 30.

    Use a class when you have several values that belong together and you want to create many objects with the same shape. In TypeScript a class also gives you a type: once Employee exists, you can write Employee as the type of a variable.

    Declaring a class

    You declare a class with the class keyword. Unlike plain JavaScript, TypeScript wants every property listed in the class body with its type, before the constructor assigns it:

    class Employee {
        name: string;
        age: number;
    
        constructor(name: string, age: number) {
            this.name = name;
            this.age = age;
        }
    }
    

    Three parts are involved:

    • Property declarations, name: string; and age: number;, tell the compiler which properties every instance has.
    • The constructor is a special method named constructor. It runs once when an object is created and sets up its properties. Its parameters have type annotations, like those of any function.
    • this refers to the object being created or used. Inside the constructor, this.name is the property, and plain name is the parameter. The line this.name = name copies the parameter into the property.

    If you leave out the property declaration, the compiler reports "Property 'name' does not exist on type 'Employee'" at the assignment.

    Creating objects and using them

    The new keyword creates an instance and runs the constructor with the arguments you give. Properties are read and changed with the dot operator:

    let emp: Employee = new Employee("Andrew", 30);
    console.log(emp.name); // Andrew
    emp.age = 40;
    console.log(emp.age);  // 40
    

    The annotation : Employee is optional, because TypeScript infers the type from new Employee(...). The compiler also checks the call. new Employee("Andrew") is rejected because an argument is missing, and new Employee(5, 30) is rejected because 5 is not a string.

    Each instance has its own copy of the properties. Changing one employee's age doesn't touch any other employee.

    Methods

    Methods are functions that belong to the class. They are written without the function keyword, with their parameter types and a return type. void means the method returns nothing:

    class Employee {
        name: string;
        age: number;
    
        constructor(name: string, age: number) {
            this.name = name;
            this.age = age;
        }
    
        printName(): void {
            console.log(this.name);
        }
    
        printEmployee(): void {
            this.printName();
            console.log(this.age);
        }
    }
    
    let emp1 = new Employee("Andrew", 30);
    emp1.printEmployee(); // prints Andrew, then 30
    
    let emp2 = new Employee("Mary", 25);
    emp2.printEmployee(); // prints Mary, then 25
    

    A method uses the object it was called on through this. That is why the first call prints Andrew and 30 and the second prints Mary and 25: the code is the same, but this is a different object. To call another method of the same object, or to read a property, you must write this. in front. Without it, the name refers to a variable outside the class and isn't found, and the compiler reports "Cannot find name".

    Gotchas

    • Annotations check, they don't convert. Types are erased when TypeScript is compiled to JavaScript. The constructor's name: string stops you from writing a wrong call in your own code, but at run time nothing verifies the argument. If a number sneaks in through a cast or untyped data, it is stored as a number.
    • A compile error doesn't stop the program. In these lessons, the compiler reports a type error but still produces the JavaScript, which runs. Read the compiler's messages as warnings you must fix.
    • Methods lose this when detached. After const f = emp1.printEmployee;, calling f() fails with "Cannot read properties of undefined", because there is no object before the dot any more. Call methods on the object: emp1.printEmployee().
    • Forgetting new. Calling a class like a plain function, Employee("Andrew", 30), is an error. A class can only be created with new.
    • Shorthand. Writing constructor(public title: string) {} declares the property and assigns it in one go. This lesson spells it out in full so each step is visible.

    The lesson's exercise: a Job class

    The exercise builds a small class, step by step.

    1. Declare the class named Job and list one property in its body: title, of type string.
    2. Add the constructor with a parameter named title of type string, so each new object receives its job title.
    3. Store the parameter. Inside the constructor, assign it to this.title. The left side is the property of the object, and the right side is the parameter.
    4. Add the method hireMe below the constructor, with return type void, since it prints and returns nothing.
    5. Print the message in hireMe: join "You're hired as a " and this.title with + and pass the result to console.log. A bare title there would not compile.
    6. Create the object. Below the class, declare job with let, annotated as Job, and set it to new Job("Software Engineer").
    7. Call the method with job.hireMe().
    class Job {
        title: string;
        constructor(title: string) {
            this.title = title;
        }
        hireMe(): void {
            console.log("You're hired as a " + this.title);
        }
    }
    
    let job: Job = new Job("Software Engineer");
    job.hireMe();
    

    Running it prints You're hired as a Software Engineer. The string "You're hired as a " ends with a space, which is what separates the words from the title. Because the text contains an apostrophe, it is written in double quotes.

    Key takeaways

    • A class is a blueprint, and new creates an instance from it.
    • In TypeScript, declare each property with its type in the class body, then assign it in the constructor.
    • Inside the class, use this to reach the object's own properties and methods.
    • Methods are declared without function, with typed parameters and a return type such as void.
    • Types are checked by the compiler and erased afterwards, so they don't change what the program does at run time.
    Keep going with TypeScriptAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free