Tom RayTom Ray
Published on
Last updated:

NestJS Course - Part 1

Ready? Let's go!

📖 TypeScript Classes

Classes are used everywhere in NestJS. Here's a simple example of a class:

class TweetService {
  // private fields
  private tweet: string
  private userId: string

  // constructor: define arguments to pass into class
  constructor(tweet: string, userId: string) {
    // set the arguments to their respective fields
    this.tweet = tweet
    this.userId = userId
  }

  // method
  getTweet() {
    return `Tweet: "${tweet}" by user with id ${userId}`
  }
}

Classes are really just special functions - they're a great way to organize your code into logical groups in an Object-Oriented fashion.

Let's go over the 3 parts of the class defined above: the constructor() method, fields and methods.

You can think of the constructor() method the same way as defining arguments required for a function.

For example, here's a function with the same arguments used in the class:

const tweetFunction = (tweet: string, userId: string) => {
  return `Tweet: "${tweet}" by user with id ${userId}`
}

tweetFunction(`I love to tweet`, 4234)

Using the constructor method in Classes is how you can define parameters that need to be passed in when the class is instantiated.

Similar to functions, when using the class, the order of the arguments is important.

Next up we have fields. Fields are variables that hold information relevant to the class.

You'll notice that the private keyword has been used. This ensures that the variable is only accessible from inside the class - the outside world cannot view or change these private fields directly.

For example, this code would not work:

const tweetService = TweetService(`I love to tweet`, 4234)
tweetService.tweet // syntax error
tweetService.userId // syntax error

Private fields are helpful when you want to enforce some encapsulation to your code.

You'll notice in NestJS that private variables are generally used by default. There's a TypeScript shorthand for defining private variables which will make your life a bit easier.

Let's refactor the TweetService above to use this shorthand:

class TweetService {
  // constructor: define arguments to pass into class
  constructor(private tweet: string, private userId: string) {}

  // method
  getTweet() {
    return `Tweet: "${tweet}" by user with id ${userId}`
  }
}

Just by adding the private keyword next to each respective argument, TypeScript takes care of assigning these arguments to private fields in the class.

Finally, we have methods.

Methods are special custom functions you define in the class to perform behaviors relevant to the class.

For example, you could add CRUD methods for the TweetService:

class TweetService {
  // constructor: define arguments to pass into class
  constructor(private tweet: string, private userId: string) {}

  // method
  getTweet() {
    return `Tweet: "${tweet}" by user with id ${userId}`
  }

  createTweet() {
    // ...
  }

  updateTweet() {
    // ...
  }

  deleteTweet() {
    // ...
  }

If you want to use this class and call a method from the class, you can do this:

// first instantiate the class
const tweetService = TweetService(`I love to tweet`, 4234)

// then call the method
tweetService.getTweet()

You might have noticed, however, that even though NestJS uses classes everywhere, you won't see any class instantiation like we've just done above.

So classes are used everywhere in NestJS but the classes are never instantiated... That seems a bit strange, right?

That's because NestJS uses a dependency injection container to instantiate classes for you.

What the hell is a dependency injection container?

It might be THE most important concept to understand in NestJS.

We'll cover this in the next part of the course which you'll receive via email tomorrow!