Share Interfaces in Angular and NestJS with Nx
Tags: angular, nestjs, nx
Published: 2022-05-17 17:25:10

---
title: Share Interfaces in Angular and NestJS with Nx
published: true
date: 2022-01-04 00:00:00 UTC
tags: angular, nestjs, nx
canonical_url: https://www.prestonlamb.com/blog/share-interfaces-in-angular-nad-nestjs-with-nx
---

## [tldr;](#tldr)

I'm a big fan of using Nx and having multiple apps in a single workspace, especially when the apps have a lot in common and a lot of code to share. This is especially helpful when dealing with interfaces for data retrieved from or sent to the server. In this article, we'll talk about how to share those interfaces between the front and back end.

This isn't the only way to manage these interfaces, but it is working well for us on a full stack project in our Nx workspace. An update can be made to the interface in one spot, and the front and back ends stay in sync. I've worked on a lot of projects where the communication breaks down and it's unclear what data should be sent or expected. That stumbling block can be eliminated by having your front and back end apps in the same workspace.

## [Setup](#setup)

If you want to follow along, create a new Nx workspace:

```sh
$ npx create-nx-workspace
```

Give the workspace a name, and then select the angular-nest option for creating the workspace. After that you can enter what you want for the remainder of the prompts. Once the dependencies are installed, you should be good to go.

When you open the project, you'll see a couple directories inside the apps directory. The three directories are `api`, your Angular app folder, and the Angular app's end to end test folder. In the libs directory is an `api-interfaces` lib.

## [Creating an Interface](#creating-an-interface)

Let's create our first interface. It'll be a simple example, one that's frequently used: a todo. In the `api-interfaces` lib, create a new file called `todo.interface.ts` next to the `api-interfaces.ts` file that was created automatically when the workspace was created. Put the following contents in the new file:

```ts
// todo.interface.ts

export interface Todo {
    id: number
    title: string;
    complete: boolean;
}
```

This will be the base interface for the todos in our app. The Angular app will use this interface for type checking, and the API will implement this interface for the entities and DTOs that are used in NestJS.

## [Creating a DTO](#creating-a-dto)

Now that we have an interface, let's create a DTO that our NestJS app can use to define the data that should be sent when creating a new todo or updating an existing one. In the `api` app, create a new file: `todo.dto.ts` and add the following:

```ts
// create-todo.dto.ts

import { Todo } from '@my-workspace/api-interfaces

export class CreateTodoDto implements Omit<Todo, 'id'> {
    title: string;
    completed: boolean;
}
```

> Note: in all likelihood you will not create this DTO in the `api` app, but in a new lib that you create for this NestJS module. To keep things simple for this demo, though, I selected the `api` folder to contain the DTOs and entities.

There are a couple things I want to point out here. First, we import our `Todo` interface from the `api-interfaces` lib, the one we created in the last section. This is the base for the DTO. We `implement` the interface to create our `CreateTodoDto`, but we use [the `Omit` utility type](https://www.typescriptlang.org/docs/handbook/utility-types.html#omittype-keys) to remove the `id` attribute from the DTO. The reason for this is because we won't have an `id` for the todo when we're creating it; that will be determined by the database. By using the `Omit` utility type and removing the `id` attribute from the DTO, we don't need to pass a `null` `id` when creating a new todo while at the same time requiring all the other attributes.

With this DTO now created, we can tell the controller what type to expect when a new todo is created. If an object with more or less attributes is passed to the endpoint, we can return a 400 with the required fields on the object.

## [Creating an Entity](#creating-an-entity)

Creating the entity is similar to the DTO, but we won't need to use the `Omit` utility type. Here's an example of the entity:

```ts
// todo.entity.ts
import { Todo } from '@my-workspace/api-interfaces';
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';

@Entity('todo')
export class TodoEntity implements Todo {
    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    title: string;

    @Column()
    completed: boolean;
}
```

The implementation here is very similar to the DTO, but we don't leave out the `id`. Instead, we mark it as the primary key and set it to be auto generated when a new todo is created. The other difference is the `@Entity()` decorator. This is required by `typeorm` to make this a table in the database where todos can be saved. Also, because the class is defined as `TodoEntity`, the table would be called `todo_entity` by default. By providing a string inside the parentheses for the `Entity` decorator, we can set the table name to `todo`.

I like to call the entity `TodoEntity` so that it's clear when I'm using it in different files that I am not using the interface. There are other ways, however, to distinguish between the two files and objects. Do whatever feels best to you!

## [The Benefits](#the-benefits)

So we just created three files for todos in our app. What's the benefit? Well, Angular is more powerful when types or interfaces or classes are used to determine how the data in your app is organized. You get auto completion from your IDE, and you're less likely to use the wrong attribute or method. In addition, with NestJS as our backend, we can easily check that the data that's sent to the backend is shaped correctly so that we don't have server errors popping up because too many attributes (or not enough) are sent along with the request.

The hard part is when you want or need these files on both the front end and the back end. Many times, those applications are in different repositories and managed by different teams. By having both applications in the same workspace, we've closed that gap. And, by having the DTO and entity implement the interface, we're assured that if the interface changes then changes will need to be made to the DTO and entity. Those two files will have errors if attributes are added or removed to the interface and they don't implement the right attributes. Thus, the shape of the data is always the same on the front and back end.

## [Conclusion](#conclusion)

I hope this article helped you with knowing how you can manage the interfaces, DTOs and entities in your application. When starting this project, I was unsure of the best way to do this same thing. I got [some ideas from Twitter](https://twitter.com/prestonjlamb/status/1425934473560870912), and then just started trying it out and came up with this method. I know there are other ways to do it; maybe even better ways. But this was a simple implementation and has worked great so far. Let me know how it goes for you