Classes

Maybe you noticed that we use the keyword new from time to time. For example, to create a new date, we need to write new Date(). That’s because Date is a class.

Just like functions, classes are another staple of programming. They are very convenient for organizing your code, with their own properties and functions (called methods).

To be honest, classes are a bit advanced, and you probably won’t create classes right away. But you’ll use pre-coded classes quite often (just like new Date()), so it’s important to have a rough idea of how they work.

Note that I expect you to have completed the previous lessons, especially the one about Functions.

Let’s dive into it!

Want to know when new lessons are available? Subscribe to the newsletter ✉️ and give a ⭐ to the GitHub repository to keep me motivated! Click here to get in touch.

Setup

Make a new folder somewhere on your computer, open it with VS Code, and create two files:

  • main.ts, where we will write our code. To start, you can add console.log("Hello!"); to it.
  • deno.json, which lets VS Code know this is a Deno project and enables the Deno extension. You can tweak settings in this file, but we’ll keep it empty for now.

Open the terminal and run the following command: deno run --watch main.ts

This command clears the terminal and reruns main.ts every time you save it (CMD + S on Mac or CTRL + S on PC).

You can use this setup to test the code provided in this lesson.

A screenshot showing VS Code running and watching a TypeScript file.

Creating a class

To create a class, you need to declare it with the class keyword, followed by its name and curly brackets {}. By convention, class names are capitalized.

Let’s create a class named Person.

main.ts
class Person {
}

Instantiating a class

To use the class, we need to create an instance of it by calling it with the new operator, followed by the class name and (). You can create as many instances of a class as you want.

Below, we instantiate our class Person twice. We store the new instances in the variables john and emily.

We now have two Person instances in our code.

main.ts
class Person {
}
 
const john = new Person();
const emily = new Person();

Properties and constructor

So far, our class Person is empty. We can give our Person instances name and age properties.

main.ts
class Person {
  name: string;
  age: number;
}
 
const john = new Person();
const emily = new Person();

Now, the class Person has two properties, but they are not assigned. It would be great to give john and emily a name and age when instantiating them.

To do that, you need to use the class constructor. The constructor looks like a function, but without the function keyword. It’s called when you instantiate the class (and only then).

We can give the constructor parameters (here, name and age). By using the this keyword, we can assign the parameters to the properties.

It’s now possible to pass arguments when we instantiate the class. We created just one class, but john and emily now each have their own name and age. And of course, everything is typed, so the code editor will help you out with autocomplete and will make sure you’re passing the right data types. Magic! 🪄✨

You can access class instance properties just like you would with objects, using a ..

main.ts
class Person {
  name: string;
  age: number;
 
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
}
 
const john = new Person("john", 30);
const emily = new Person("emily", 35);
 
console.log(john.name, john.age);
console.log(emily.name, emily.age);

Logging properties.

Methods

Methods are functions specifically created for a class. They are very useful because they have direct access to the class properties. They also have access to other methods, so a method can call another method. But this is getting meta. 🥸

Methods are written like functions, but without the function keyword. You have to declare them inside the class. A class can have as many methods as you want.

For example, let’s create a method called makeOlder. Each time it’s called, it will add 1 to the age property.

To call a method, use . right after an instance or a variable storing an instance, then type the name of the method followed by ().

Below, we call the makeOlder method three times on john. We instantiated him with an age of 30, but when we log his age, it’s now 33!

And since all instances are independent, emily is still 35! Of course, emily also has the makeOlder method. Feel free to test it!

main.ts
class Person {
  name: string;
  age: number;
 
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
 
  makeOlder() {
    this.age = this.age + 1;
  }
}
 
const john = new Person("john", 30);
const emily = new Person("emily", 35);
 
john.makeOlder();
john.makeOlder();
john.makeOlder();
 
console.log(john.name, john.age);
console.log(emily.name, emily.age);

Using methods.

Calling the method makeOlder three times is not very convenient. Just like functions, methods can have parameters. Let’s update our code to pass a number of years to the method.

Just like function parameters, method parameters are typed, which is very convenient and helps you avoid typos and bugs.

main.ts
class Person {
  name: string;
  age: number;
 
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
 
  makeOlder(year: number) {
    this.age = this.age + year;
  }
}
 
const john = new Person("john", 30);
const emily = new Person("emily", 35);
 
john.makeOlder(3);
 
console.log(john.name, john.age);
console.log(emily.name, emily.age);

Using methods with parameters.

Instead of using console.log and manually passing the instance properties, we could also create another method to log the ages.

As you can see, classes — with their properties and methods — can be a great way to organize your code!

main.ts
class Person {
  name: string;
  age: number;
 
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
 
  makeOlder(year: number) {
    this.age = this.age + year;
  }
 
  log() {
    console.log(`Hi! I'm ${this.name} and I'm ${this.age} years old.`);
  }
}
 
const john = new Person("john", 30);
const emily = new Person("emily", 35);
 
john.makeOlder(3);
 
emily.log();
john.log();

Using another method.

Exporting and importing

Just like functions, it’s pretty common to keep classes in their own file and export/import them.

Create a new file called Person.ts and move your class into it. Don’t forget to add export default in front of it to make it available to the rest of your scripts.

Person.ts
export default class Person {
  name: string;
  age: number;
 
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
 
  makeOlder(year: number) {
    this.age = this.age + year;
  }
 
  log() {
    console.log(`Hi! I'm ${this.name} and I'm ${this.age} years old.`);
  }
}

And now you can easily import it and use it in main.ts, which is now much simpler and easier to understand!

main.ts
import Person from "./Person.ts";
 
const john = new Person("john", 30);
const emily = new Person("emily", 35);
 
john.makeOlder(3);
 
emily.log();
john.log();

Documentation

Just like functions, you can document your classes using the JSDoc syntax.

Below, I have documented the class as well as all its methods. For each one, I added an example. Now, the documentation will pop up in VS Code when you start typing their names or when hovering over them. Very convenient!

People.ts
/**
 * Represents a person with a name and age.
 *
 * @example
 * ```ts
 * const person = new Person('John', 30);
 * ````
 */
export default class Person {
  name: string;
  age: number;
 
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
 
  /**
   * Increases the age of the person by a specified number of years.
   *
   * @example
   * ```ts
   * person.makeOlder(5);
   * ```
   *
   * @param year - The number of years to add to the person's age.
   */
  makeOlder(year: number) {
    this.age = this.age + year;
  }
 
  /**
   * Logs a message to the console with the person's name and age.
   *
   * @example
   * ```ts
   * person.log();
   * ```
   */
  log() {
    console.log(`Hi! I'm ${this.name} and I'm ${this.age} years old.`);
  }
}

Using documentation.

Conclusion

Congratulations! You wrote your first class! While you might not create a lot of them for your analyses and future projects, you will use a looooooot of them! And as you just saw, using them is very easy. 🤗

There’s a lot more to learn about classes — like inheritance, for example. But if you ever need to dive into that, it’ll mean you’ve become quite a good TypeScript coder! And by then, you’ll be able to read more technical documentation and understand it.

And if not, well, you can always reach out to me. I’ll be happy to write another lesson! 😁

Enjoyed this? Want to know when new lessons are available? Subscribe to the newsletter ✉️ and give a ⭐ to the GitHub repository to keep me motivated! Get in touch if you have any questions.