Hello! In this new series, we build a RESTful application with TypeScriptExpress. The course is going to cover the fundamental concepts of the express framework and tools like MongoDB. Some basic knowledge of TypeScript would be useful, as we focus on Express here.

I will update the repository with the current state of the application as the course progresses. Feel free to give it a star! It is available at this address: mwanago/express-typescript. You can use it as a boilerplate if you would find it useful.

TypeScript Express tutorial #1

Express is a framework for Node.js used to build the backend for web applications. It is unopinionated, meaning that you can use it in a manner in which you see fit. In this tutorial, I present a way that works for me while working with the TypeScript Express.

To test our application we use Postman. To install it, visit getpostman.com.

Let’s give it a try!

1

npm run dev

Middleware

Middleware functions have access to the request and response objects. It can attach to any place in the request-response cycle. A third argument that middleware receives is the next function. When called, the next middleware in the chain is executed. An example of a middleware is the get callback that handles the HTTP GET request that we’ve written above. It is a very specific middleware that executes on a particular case. They can also perform more generic tasks. Let’s create a very simple logger middleware that will log to console what requests were made.

In this example, as soon as someone sends the GET request to the /hello path, “GET /hello” will be printed in the console in which the app runs. In fact, it runs even when someone requests a page that you don’t have a handler for.

Thanks to calling next(), the control of the request can be passed further. If you create a middleware that neither ends the request-response cycle (for example by sending a response) or calls the next function, the request will not finish with a valid response.

There are a lot of ready to use middlewares that you can attach to your application and you will have plenty of chances to see some of them in this course. A crucial one is the body-parser. It parses the body of the incoming request and makes it available under the request.body property. In this example, we use the bodyParser.json middleware that parses the json data.

1

npm install body-parser

1

2

3

4

5

6

7

8

9

10

11

12

import*asexpress from'express';

import*asbodyParser from'body-parser';

constapp=express();

app.use(bodyParser.json());

app.post('/',(request,response)=>{

response.send(request.body);

});

app.listen(5000);

The body was sent back to us thanks to running response.send(request.body). Without the body parser, the request.body property wouldn’t be accessible.

As we go further, we explain more advanced concepts connected to the middleware.

Routing

The app object has a set of functions that attach callbacks to HTTP requests performed to specified paths, just like the examples above with app.get and app.post. You can also attach callbacks to other HTTP methods like POST, PUT, PATCH and DELETE. You can look up a whole list of them in the documentation.

Another way to set up routing is to use the router object. Once you create a router object you can call the methods like get, put, patch and delete just like on the app object.

1

2

3

4

5

constrouter=express.Router();

router.get('/',(request,response)=>{

response.send('Hello world!');

});

The only thing left that is required is to use the router.

1

app.use('/',router);

As you can see by the usage of app.use, the router instance is just a middleware that you can attach to your application.

The addresses of the routes are a combination of paths provided for the app.use and the router.METHOD.

1

2

3

4

5

router.get('/hello',(request,response)=>{

response.send('Hello world!');

});

app.use('/api',router);

The code above results in creating a route /api/hello that responds with a text “Hello world!”.

Request

The request object contains information about the HTTP request, such as headers, the request query string, and parameters.

Its the most important method is called send. It sends the HTTP response so that the client can receive it. The function accepts different types of data: strings, objects (Array included), or Buffers. Send ends the response process with data, but you can also end it without any data using the end function.

The same as with the request, we dive more into the response object as we go.

Controllers

A common way of structuring an Express application is called Model-View-Controller. Some of the key components of MVC are controllers. They contain the logic of the application and deal with handling client requests. Since this course covers TypeScriptExpress, we use classes. For the sake of readable code, I also create a class for the app instance itself.

src/server.ts

1

2

3

4

5

6

7

8

9

10

11

import App from'./app';

import PostsController from'./posts/posts.controller';

constapp=newApp(

[

newPostsController(),

],

5000,

);

app.listen();

src/app.ts

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

import*asexpress from'express';

import*asbodyParser from'body-parser';

classApp{

public app:express.Application;

public port:number;

constructor(controllers,port){

this.app=express();

this.port=port;

this.initializeMiddlewares();

this.initializeControllers(controllers);

}

privateinitializeMiddlewares(){

this.app.use(bodyParser.json());

}

privateinitializeControllers(controllers){

controllers.forEach((controller)=>{

this.app.use('/',controller.router);

});

}

publiclisten(){

this.app.listen(this.port,()=>{

console.log(`Applisteningontheport${this.port}`);

});

}

}

export defaultApp;

src/posts/posts.interface.ts

1

2

3

4

5

6

7

interfacePost{

author:string;

content:string;

title:string;

}

export defaultPost;

src/posts/posts.controller.ts

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

import*asexpress from'express';

import Post from'./post.interface';

classPostsController{

publicpath='/posts';

publicrouter=express.Router();

private posts:Post[]=[

{

author:'Marcin',

content:'Dolor sit amet',

title:'Lorem Ipsum',

}

];

constructor(){

this.intializeRoutes();

}

publicintializeRoutes(){

this.router.get(this.path,this.getAllPosts);

this.router.post(this.path,this.createAPost);

}

getAllPosts=(request:express.Request,response:express.Response)=>{

response.send(this.posts);

}

createAPost=(request:express.Request,response:express.Response)=>{

const post:Post=request.body;

this.posts.push(post);

response.send(post);

}

}

export defaultPostsController;

The code above results in creating the route named /posts that responds on the GET and POST request, storing and displaying the list of posts. In the upcoming parts of the Typescript Express course, we continue to use controllers to structure our code.

The getAllPosts and createAPost are arrow functions because they access properties of an instance of the class. Since they are passed to the router and not called directly, the context changes. You can achieve the same result by calling this.router.get(this.path,this.getAllPosts.bind(this))

Summary

In this article, we’ve grasped the very basics of building RESTful applications with TypeScript Express. It covered starting up a project, the use of middleware, routing and what are the request and response objects. The code that we write is structured in controllers and available in the repository.I hope that you will find it helpful. The repository will grow a lot in the upcoming future because there are more parts of the tutorial coming.

I’ve found a few typos. For example at the beginning you wrote tsconfig.js instead of .json and later on you wrote import Post from ‘./post.interface’; instead of import Post from ‘./posts.interface’; Just minor stuff in an overall great tutorial.

Thanks, I fixed the tsconfig.js typo. The other file you’ve mentioned is called posts.interface because it exports the Post interface (the singular form), and not the Posts interface (the plural form). Thank you for contributing!