TypeScript Express tutorial #3. Error handling and validating incoming data

Express JavaScript

This entry is part 3 of 15 in the TypeScript Express tutorial

Since not always everything goes perfectly, you need to expect the unexpected. To prepare for that, we cover TypeScript Express error handling and incoming data validation. Just as before, the repository for the tutorial is mwanago/express-typescript. If you find it helpful, feel free to give it a star.

Express Error handling

In the previous part of the tutorial, we wrote a handler function to return a post with a specific ID:

There is a slight problem with it though. If a post with a particular ID does not exist, its value in the callback function is null. We then send it, resulting in a response with a code 200 OK. It indicates that everything went fine and the user got a document that he requests, but this post is not empty in our database: it just does not exist. There is a big list of status codes that you can use, but in this case, we use 404 Not Found.

The 200 OK code if default when you use the send function. To change that, you need to call the status function, before using send.

Now when someone tries to access a post that does not exist, he is informed about what went wrong.

express error handling postman

This outcome is good, but we can make our code better. We want to create errors from our route handlers and let the middleware worry about sending them. There is a default error handler built into Express. To use it, you need to call the next function with an argument (other than the string ‘route’).

Handling the error in this way results in a 500 Internal Server Error and the error page is rendered.

express error handling default postman

If we want to handle it differently, we need to create our Express error handling middleware

Express Error handling middleware

First, let’s create a class that we are going to use to throw errors.

src/exceptions/HttpException.ts

If  you would like to know more about the Error object and the errors in general, check out Handling errors in JavaScript with try…catch and finally

Defining Express error handling middleware is almost the same as any other middleware, except we use four arguments instead of three, with the error being the additional first argument.

src/middleware/error.middleware.ts

Since Express runs all the middleware from the first to the last, your error handlers should be at the end of your application stack. If you pass the error to the next function, the framework omits all the other middleware in the chain and skips straight to the error handling middleware which is recognized by the fact that it has four arguments.

The last thing to do is to attach the error handling middleware to our app:

src/app.ts

We can use the HttpException in the same manner when a post that the user wants to delete or modify a post that doesn’t exist. That would mean creating the HttpException in the same way. To avoid redundant code, we can prepare an exception just for that situation.

src/exceptions/PostNotFoundException.ts

Validating incoming data

Another thing worth mentioning is validating input data to prevent the users from creating invalid documents in our collections. To do that I use a package called class-validator with an additional middleware.

The first thing to do is to create a data transfer object (DTO) file that carries data between our functions. It contains specification on how should the incoming data look.

src/posts/post.dto.ts

To use decorators with TypeScript, you need to add   to your

When we got that down, the only thing left is the validation middleware. Since the body of our request is a plain object, we need to transform it into our class first. To do that, I use the class-transformer package.

src/middleware/validation.middleware.ts

The class-validator package validates the object, and if it finds some errors, the middleware calls the next function with the error details. Since we pass an error into the next function, the Express error middleware that we described above takes care of it. The errors variable keeps an array of errors, each of them having the constraints object with the details. This simple example creates a string of all of the issues.

The 400 Bad Request status code means that there is something wrong with the request that the client sent.

If you need to, you can also pass an array so that it can be easier to iterate over on the frontend

A thing left to do is to attach the middleware:

Since we want it only on some of our endpoints, we attach it straight before the handler functions. In the example above, the middleware validates the data before the   function runs.

Validating the PATCH handler data

It would be great to use that validation in our updating logic too. There is a small catch: in our CreatePostDto class, all fields are required, and we are using HTTP PATCH that allows for updating just some of the properties without passing the rest of them. There is an easy solution for that thanks to the skipMissingProperties option.

src/middleware/validation.middleware.ts

It skips validating all the properties that are missing, so if you are updating just a part of the document, it doesn’t cause an error just because a required property is not present.

Summary

In this article, we’ve covered Typescript Express error handling. To do that we’ve created an Express error handling middleware and used the next function with an additional argument to pass the error to the error handling middleware. Aside from that, we’ve learned how to validate incoming data in our POST and PATCH handlers using the class-validator package. All those new skills will surely be useful, especially because the next part of the course will cover registering users and authentication.

Series Navigation<< TypeScript Express tutorial #2. MongoDB, models and environment variablesTypeScript Express tutorial #4. Registering users and authenticating with JWT >>
Subscribe
Notify of
guest
12 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Predrag Stojadinovic
5 years ago

I’m having a problem with CreatePostDto class because it does not have a constructor:

return new TSError(diagnosticText, diagnosticCodes)
^
TSError: ⨯ Unable to compile TypeScript:
src/posts/post.dto.ts(5,9): error TS2564: Property ‘author’ has no initializer and is not definitely assigned in the constructor.
src/posts/post.dto.ts(8,9): error TS2564: Property ‘content’ has no initializer and is not definitely assigned in the constructor.
src/posts/post.dto.ts(11,9): error TS2564: Property ‘title’ has no initializer and is not definitely assigned in the constructor.

Only when I add a constructor with all 3 attributes, then it compiles…

Is there a way to not require the constructor?

sokun
sokun
5 years ago

Hi i am new with this. How can i return json message when validate incoming data. Thank you

Mauro
Mauro
4 years ago

Hi.
The findById not found (404) is not working for me.
I’ve tried running the GIT version (branch 3) with the same result:

(node:28712) UnhandledPromiseRejectionWarning: CastError: Cast to ObjectId failed for value “5cca196d241e220934ad4e72a” at path “_id” for model “Post”

Krit Narayan
4 years ago

Hi Marcin, I’ve facing Authentication token missing issues while inserting data. Please can you let me know what is the issue

Sahil Kariyania
4 years ago

class-transformer was throwing some errors[1]
I had to import ‘reflect-metadata’;

resolution in validation.middleware.ts
import ‘reflect-metadata’;
import { plainToClass } from ‘class-transformer’;
import { validate, ValidationError } from ‘class-validator’;

[1] Error: Uncaught TypeError: Reflect.getMetadata is not a function

park joonmo
park joonmo
4 years ago

thanks for the tutorial! it’s really helpful

Fernard89
Fernard89
4 years ago

Hi, thanks for the article. However, you don’t mention how to really handle Mongoose errors in a typed environment. The HttpException is explicitly created only for the most obvious cases and its interface does not expect any programming errors such as CastError. Do you know a clean and efficient way to prepare your application for such errors?

Cheers.

Hiro
Hiro
3 years ago

when used PostNotFoundException and I recieved this error:
(node:17496) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.
(Use node --trace-deprecation ... to show where the warning was created)

Currently, I using node v14.15.0 and npm 6.14.8 (latest)
Please, tell me why?

Last edited 3 years ago by Hiro
scott
scott
2 years ago

it’s so nice to find this tutorial. it’s helped me a lot. thank you. And Do you want to write a post about the class-validator and class-transform? That part is hard for me. hahaha
How can it do the transform and validate? it’s a magic。

Last edited 2 years ago by scott
vietphongtech
vietphongtech
1 year ago

thanks