Backend Data Validation Using Typescript Interfaces

Ömer Yalhı
6 min readMay 4, 2019

The Problem

When writing a REST API, a common problem I face is validating and updating an object. I need to make sure the update object has only the certain ‘allowed’ properties so that I don’t inadvertently change protected properties, such as a password or any other field that I don’t want it to change.

I usually do this by checking each property manually and updating the object accordingly. However, I wanted a better, more re-usable approach, so that I don’t have to manually check each property. In this article, I try to explain the steps and the final solution that I’ve come up with.

Let’s assume we have the following User interface:

Approach #1 (buggy)

Let’s assume that we have a REST API where it allows update to the user. Updatable properties are `firstName`, `lastName` and `birthYear`. We could write the route as follows:

Here is what is happening:

1. find the user via the `id` from the `params`

2. if not found, send 404 and return

3. get the requested properties to change, which are in `req.body`

4. create a new object that updates the properties with the `json` objects’ keys. Here we have a problem though. The new updated user will add any property that is sent via the JSON object or update a property that is not allowed, such as a password. For example, if the JSON object is the following:

our code will inadvertently change the password and add a new property `homeTown` which doesn’t exist in our interface. Which is far from ideal let’s say.

5. update users array with the new user object

6. send back the updated user

Approach #2

A better approach would be to change only updatable properties:

1. find the user via the `id` from the `params`

2. if not found, send 404 and return

3. get the requested properties to change, which are in `req.body`

4. if exists update each property with the new value, if not use the current value

5. send back the updated user

This code would run without bugs. However, what if we had many more properties? What if the properties need to change in the future? We need a more robust way to write it.

Approach #3

With the help of TypeScript let’s define an interface with the updatable properties of our user object:

What if we could have access to UpdateUserDto interface’s keys? We could then iterate the interface keys and update the matching key in the user object. With the help of a custom transformer, we can do just that!

The custom transformer we are going to use is, `ts-transformers-key`. It has 2 transformers, one takes the given type and outputs an array of its keys, very handy. The other is used to compile the `keys` function correctly, a necessary part of the library, but we don’t use it directly. I go into details on how to install the complete project step by step later below.

Here is the third version of our route:

1. find the user via the `id` from the `params`

2. if not found, send 404 and return

3. get the requested properties to change, which are in `req.body`

4. get the all the keys that we are allowed to change, defined by the `UpdateUserDto` data transfer object

5. go over each allowed property, and if it matches the requested key, assign it. If not, then we use the original value. Here, going over the `UpdateUserDto` we are making sure that we are only changing the allowed properties. If the `json` object had a property, let’s say `password`, because it didn’t exist in the dto, it would be ignored.

6. send back the updated user

Approach #4

Usually in my apps, instead of just stripping out the illegal properties and using the legal properties, I would like to reject the request all-together. I feel that the front end should send the request correctly and not rely on the back end to fix it’s errors. Thus my approach would be the following:

1. find the user via the `id` from the `params`

2. if not found, send 404 and return

3. get the requested properties to change, which are in `req.body`

4. get all the keys that we are allowed to change, defined by the `UpdateUserDto` data transfer object

5. from the requested JSON object, filter out the keys that don’t exist in the UpdateUserDto

6. length is more than 0 if there are keys that are not present in the DTO, the length would be a truthy value. if so, reject the request.

7. go over each allowed property, and if it matches the requested key, assign it. If not, then we use the original value. Here, going over the `UpdateUserDto` we are making sure that we are only changing the allowed properties. If the `json` object had a property, let’s say `password` because it didn’t exist in the DTO, it would be ignored.

8. send back the updated user

This was our final approach to the problem.

Step By Step Project Setup

Note that I am using Mac and fish shell (which I highly recommend), so your commands might differ slightly if you are using a different operating system or shell.

Clone the minimal Node / Express with TypeScript boilerplate. As the name suggests this is a minimal Node / Express app using TypeScript, so I won’t get into details. You can clone or download the code here:

https://github.com/oyalhi/typescript-node-express-minimal-boilerplate

After cloning or downloading, go into the project folder, install the dependencies and open your editor, here I’m using VS Code:

Let’s run the boilerplate in watch mode by simply running the `watch` script which simply runs `nodemon` that uses the `nodemon.json` config file in the root of the folder:

If all went well, we should see the message that the server is listening on port 3000. We can exit the app and install the necessary libraries.

First we need to install the custom transformer, `ts-transformers-key`:

Unfortunately, TypeScript itself does not currently provide an easy way to use custom transformers. But with the help of a custom library `ttypescript` (note the double ‘t’) we can easily compile our code. Let’s install the library:

We now need to add the following line to tsconfig.json to successfully compile our transformer:

So the final version of `tsconfig.json` looks like this:

Finally we need to tell `ts-node` to use the newly installed `ttypescript` compiler.

First update the `start` script in `package.json`:

Then we update the `nodemon.json`:

That’s it, we’ve updated nodemon as well the `start` script. Just run `yarn start` or `yarn watch` and implement our approach to the code. If you are feeling lazy, you can find the final code here:

https://github.com/oyalhi/update-using-dto

Conclusion

Updating an object is a common scenario in a back end application. I wanted a solution that did not require a manual update of the code every time the requirements for an object has changed. Also, a solution that I can use in any project without rewriting the same boilerplate code.

We went through 4 solutions, each one improving the previous version. The first approach was buggy, had the possibility of changing our object. The second approach was too manual, required to assign each property manually. The third approach solved the problem; however was accepting illegal requests, though only using accepted keys. Our fourth and final approach rejected illegal requests for a rock solid approach.

I wanted to go one step further and create a generic function that could be used anywhere easily; however, we cannot use the `keys` dynamically and thus can’t create a generic function. But for now, what we have should suffice.

I hope you liked it!

--

--

Ömer Yalhı

Web and Mobile Developer, Creator of the free app: Steps Leaderboard, w/ Live Step Counting:iTunes store link: https://itunes.apple.com/app/id131208