When and how to use interfaces and classes in TypeScript
Tags: typescript, webdev, tutorial, productivity
Published: 2021-12-02 17:39:27

**Written by [Gapur Kassym](https://blog.logrocket.com/author/gapurkassym/) ✏️**

Interfaces and classes are the fundamental parts of object-oriented programming (OOP). [TypeScript](https://blog.logrocket.com/whats-new-in-typescript-4-2/) is an object-oriented JavaScript language that, from ES6 and later, supports OOP features like interface, class, and encapsulation.

But when should we use interfaces, classes, or both at the same time? If you are a new or confused using interfaces and classes, this piece is for you.

In this article, I’ll show you what interfaces and classes are and when to use one or both of them in TypeScript.

## What is a class in TypeScript?

Before we get started, we need to know what a TypeScript class is. In object-oriented programming, a class is a blueprint or template by which we can create objects with specific properties and methods.

Typescript provides additional syntax for type checking and converts code to clean JavaScript that runs on any platform and browser. Classes are involved in all stages of code. After converting the TypeScript code to a JavaScript file, you can find them in the final files.

The class defines the template of the object, or what it is and what it does. Let’s create a simple class with properties and methods so we can see how it will behave.

First, I’m going to create a `Developer` class through the following lines of code:

```typescript
class Developer {
  name?: string; // string or undefined
  position?: string; // string or undefined
}
```

We describe the class with properties `name` and `position`. They contain types like `string` and `undefined`.

Next, let’s create an object via the `Developer` class using the `new` keyword:

```typescript
const developer = new Developer();
developer.name // it outputs undefined
developer.position // it outputs undefined
```

When we call `developer.name`, it returns `undefined` because we didn’t assign initial values. In order to create an object with values in TypeScript, we can use the [`constructor`](https://en.wikipedia.org/wiki/Constructor_(object-oriented_programming)) method. The constructor method is used to initialize and create objects.

Now we update our `Developer` class with the following code:

```typescript
class Developer {
  name: string; // only string
  position: string; // only string

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

In the code above, we added the `constructor` method to initialize the properties with values.

Now we are able to set the `name` as `Gapur` and `position` as `Frontend Developer` using the following code:

```typescript
const developer = new Developer("Gapur", "Frontend Developer");
developer.name // it outputs Gapur
developer.position // it outputs Frontend Developer
```

Last, as I mentioned earlier, the class has methods that how the object should act. In this case, any developer develops applications, therefore, the `Developer` class has the method `develop`.

Thus, a `developer` object can perform a development action:

```typescript
class Developer {
  name: string;
  position: string;

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

  develop(): void {
    console.log('develop an app');
  }
}
```

If we run the `develop` method, it will execute the following `console.log` statement:

```typescript
developer.develop() // it outputs develop an app
```

## What is an interface in TypeScript?

An interface is a structure that acts like a contract in your application, or the syntax for classes to follow. The interface is also known as duck printing, or subtyping.

The interface includes an `only` method and field declarations without implementation. We can't use it to create anything. A class that implements an interface must have all fields and methods. Therefore, we use them for type checking.

When TypeScript converts all code to JavaScript, the interface will disappear from the JavaScript file. Therefore, it is a helpful tool during the development phase.

We should use an interface for the following:

*   Validating specific structure of properties
*   Objects as parameters
*   Objects returned from functions

Now, let’s declare the interface through the following lines of code:

```typescript
interface InterfaceName {
  // variables;
  // methods;
}
```

We can only contain declarations of variables and methods in the body of the interface. Let’s create an `IDeveloper` interface for the previous `Developer` class:

```typescript
interface IDeveloper {
  name: string
  position: string
  develop: () => void
}

class Developer implements IDeveloper {
  name: string;
  position: string;

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

  develop(): void {
    console.log('develop an app');
  }
}
```

In the above code, our `IDeveloper` interface contains the variables `name` and `position`. It also includes the `develop` method. So the `Developer` class implements the `IDeveloper` interface. Thus, it must define two variables and a method.

If the `Developer` class doesn’t implement any variables, TypeScript will show an error:

```typescript
class Developer implements IDeveloper {
  // error Class 'Developer' incorrectly implements interface 'IDeveloper'.
  name: string;

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

  develop(): void {
    console.log('develop an app');
  }
}
```

## Interfaces vs classes

So when should we use classes and when should we use interfaces?

Before we start, I want to share with you the powerful TypeScript `static` property that allow us to use fields and methods of classes without creating instance of class.

I am going to make a class with a static method using the previous `Developer` class:

```typescript
class Developer {
  static develop(app: { name: string, type: string }) {
    return { name: app.name, type: app.type };
  }
}
```

Now, we can just call the `Developer.develop()` method without instantiating the class:

```typescript
Developer.develop({ name: 'whatsapp', type: 'mobile' })
// outputs: { "name": "whatsapp", "type": "mobile" } 
```

Great!

Also, we can use classes for type checking in TypeScript. Let’s create an `App` class using the following code:

```typescript
class App {
  name: string;
  type: string;

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

Let’s modify our `Developer` class:

```typescript
class Developer {
  static develop(app: App) {
    return { name: app.name, type: app.type }; // output the same
  }
}
```

Now I will make an `App` instance and invoke `Developer.develop()` with an argument object:

```typescript
const app = new App('whatsapp', 'mobile');
Developer.develop(app);
// outputs the same: { "name": "whatsapp", "type": "mobile" } 
```

`Developer.develop(app)` and `Developer.develop({ name: 'whatsapp', type: 'mobile' })` output the same content. This is awesome, but the second approach is more readable and flexible.

Plus, we can check the type of arguments. Unfortunately, to do so, we need to create an object. So how can we improve it? This is where the interface comes in!

First, I am going to change the `App` class to an interface with the following code:

```typescript
interface App {
  name: string
  type: string
}

class Developer {
  static develop(app: App) {
    return { name: app.name, type: app.type }; // output the same
  }
}
```

In the code above, we didn’t change the body of the `Developer` class and didn't create an instance of `App`, but the result was the same. In this case, we saved a lot of time and code typing.

## Conclusion

When should we use classes and interfaces? If you want to create and pass a type-checked class object, you should use TypeScript classes. If you need to work without creating an object, an interface is best for you.

Eventually, we opened two useful approaches: blueprints and contracts. You can use both of them together or just one. It is up to you.

Thanks for reading — I hope you found this piece useful. Happy coding!

---

## Writing a lot of TypeScript? [Watch the recording](https://blog.logrocket.com/typescript-meetup-recap/?utm_source=social&utm_medium=organic&utm_campaign=21Q3_WB_TS-Tech-Meetup0930#utm_source=social&utm_medium=organic&utm_campaign=21Q3_WB_TS-Tech-Meetup0930) of our recent TypeScript meetup to learn about writing more readable code.

[![TypeScript meetup header](https://blog.logrocket.com/wp-content/uploads/2021/07/typescript-4-4-more-readable-code.png)](https://blog.logrocket.com/typescript-meetup-recap/?utm_source=social&utm_medium=organic&utm_campaign=21Q3_WB_TS-Tech-Meetup0930#utm_source=social&utm_medium=organic&utm_campaign=21Q3_WB_TS-Tech-Meetup0930)