TypeScript Classes and Constructors blog post

TypeScript Classes and Constructors

Todd Motto

24 Apr, 2019

TypeScript

5 minutes read

We’re ready to learn how to add TypeScript to our ES6 classes. We’ll get there, but first let’s talk about classes in JavaScript, where they came from and their typical ES5 "constructor" syntax. From there, we’ll look at how we can add TypeScript to ES6 classes – understanding which pieces we need.

This post is the first in the series on TypeScript Classes, we’ll also be covering the following in this and later posts to give you a kick start into getting started with TypeScript classes and how to do them the "TypeScript way":

  • TypeScript Classes and Constructors (this post!)
  • Public and Private Members
  • Static Properties and Methods
  • Abstract Classes

Classes and Constructors

ES6 classes in JavaScript are simply syntactic sugar for creating our own constructor functions and prototypal inheritance. You may be familiar with things like .prototype in JavaScript which allow us to inherit properties from other Objects, even classes. When we create a class we are essentially creating a less verbose and sugar syntax version of the old "prototype and a constructor" function approach.

To get a better understanding of the "old way" before we continue to typing ES6 classes, we’re going to create a JavaScript function and treat it as a constructor. We’ll then learn how to type a class by refactoring it from ES5 to ES6. It’s also worth mentioning that all these ES6 features, such as classes, are perfectly valid TypeScript – as TypeScript is a superset of JavaScript. Therefore any valid JavaScript is also valid TypeScript.

Let’s take a look at a simple Pizza constructor function, this is the ES5 way of creating a class and constructor, the function acting as our constructor:

function Pizza(name: string) {
 this.name = name; 
}

We pass the name argument through our constructor, and can simply type it as string.

Note: If you have in your tsconfig.json "strict": true then this will cause an error because it is conflicting with our plain JavaScript approach.

Next let’s define a prototype method called addTopping – which means that we can extend our class with our own custom methods:

function Pizza(name: string) {
 this.name = name; 
 this.toppings = [];
}

Pizza.prototype.addTopping = function addTopping(topping: string) {
 this.toppings.push(topping);
};

We’ve completed so far:

  • Class definition (Pizza is the class name)
  • Constructor function (the function Pizza acts as the constructor)
  • Class method (addTopping, which is added to the prototype chain and not the class directly)

Here’s how we might use it when put together:

function Pizza(name: string) {
 this.name = name; 
 this.toppings = [];
}

Pizza.prototype.addTopping = function addTopping(topping: string) {
 this.toppings.push(topping);
};

const pizza = new Pizza('Pepperoni');
pizza.addTopping('pepperoni');

This would now give us:

// Pizza { name: "Pepperoni", toppings: ["pepperoni"] }
console.log(pizza);

The important piece here to visually see in our developer tools is Pizza {...}. This signifies the Object we’re viewing is an instance of Pizza. Yes that’s right, instanceof was created for this purpose:

pizza instanceof Pizza; // true

TypeScript and ES6 Classes

So now we’ve covered the "old way" of doing things, let’s refactor what we’ve learned and see how we can do this with ES6 classes and a sprinkling of TypeScript.

Class Properties and Constructors

Before we had a "class", "constructor" and "prototype methods" which were all separately defined. There is no major difference between the ES5 and ES6 way, but by refactoring we can immediately see a more self-contained and clearer picture as to why ES6 classes landed in JavaScript and TypeScript:

class Pizza {
  name: string;
  toppings: string[] = [];

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

At this point we’ve defined both the class and constructor via their respective keywords. Prototypal inheritance also becomes much simpler with ES6 classes, via the extends keyword.

Notable changes include the constructor is now "inside" our class. The constructor is now explicitly defined – unlike the ES5 way which we had to assume / work out was in fact a constructor.

One major difference is that in TypeScript we need to declare the class properties and their respective types upfront – typically you’d place these at the top of the class.

We also define our toppings property as an array of strings, and then also initialise the value with an empty array. This is interestingly done outside of the constructor – as it is not always necessary to add it to the constructor itself.

Defining Class Methods

We’ve one more task – adding methods to our class! Let’s make sure we can add some pizza toppings by adding our addTopping method (note how much simpler this has become):

class Pizza {
  name: string;
  toppings: string[] = [];

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

  addTopping(topping: string) {
    this.toppings.push(topping);
  }
}

Methods declared as above are known as "instance methods" and can only be accessed when creating an instance of a class, i.e. new Pizza(X).addTopping(Z);

If we want to test this out we can do like before:

class Pizza {
  // ...

  addTopping(topping: string) {
    this.toppings.push(topping);
  }
}

const pizza = new Pizza('Pepperoni');
pizza.addTopping('pepperoni');

console.log(pizza);

And there we have it! Your introduction to TypeScript classes, constructors, prototypes and methods.

If you’d like to explore TypeScript more deeply and understand the language to the fullest, I’d love to keep teaching you via my TypeScript Courses, which will take your skills from "understanding a little bit" to fully mastering TypeScript and its advanced features!

About the author

Todd Motto profile picture

Todd Motto

GDE Google Developer Expert

Todd is the Founder of Ultimate Courses. With a passion for Angular, TypeScript and JavaScript, Todd leads the online courses creation and has written hundreds of articles on front-end web development and beyond. He specialises in breaking down complex topics and understands the critical mission of learning new technology fast, comprehensively and the right way.

Love the post? Share it!

Lots of time and effort go into all our blogs, resources and demos,
we'd love it if you'd spare a moment to share them!

Explore our TypeScript courses

Get started today and join over 50,000 developers.