TypeScript icon Get 42% off the TypeScript Bundle!

See the bundle then add to cart and your discount is applied.

days
hours
mins
secs

TypeScript Classes and Constructors

Apr 24, 2019 4 mins read

TypeScript post
TypeScript icon

Want expert TypeScript skills? Here's what you need to know.

Show Me View TypeScript courses

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.

Exploring JavaScript Array Methods cover

⚡️ FREE eBook: 🔥 ForEach, Map, Filter, Reduce, Some, Every, Find

Todd Motto “This book is straight to the point, syntax exploration, comprehensive guide, real-world examples, tips and tricks - it covers all you need Todd Motto, author of Exploring JavaScript Array Methods

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!