Note: This post is part of Learn How to Use TypeScript With Node.js and Express.js series. Click here to see the first post of the series.
Table of Contents
Getting Started
First things first, we need to create the directory for our application:
mkdir express-typescript
Time to set up our package.json file where we can define all our dependencies as well as executable scripts.
npm init
Once this script is run, it will ask you the following questions:
package name: (src) express-typescript
version: (1.0.0)
description:
entry point: index.ts
test command:
git repository:
keywords:
author:
license: (ISC)
Feel free to provide the correct details. For now, the only information we cared to provide is the package name
and the entry point
set to index.ts.
Installing Dependencies
Since we are going to work with Express.js, we need to install Express.
npm i --save express
We need to install TypeScript as well as Express types to take advantage of TypeScript, but in this case, we will install them as part of the dev dependencies.
npm i --save-dev typescript @types/express
So far, this is how your package.json
should look like:
{
"name": "express-typescript",
"version": "1.0.0",
"description": "RESTful API Example of using Express with Typescript",
"main": "index.ts",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Andrés Reales",
"license": "ISC",
"dependencies": {
"express": "^4.17.1"
},
"devDependencies": {
"@types/express": "^4.17.11",
"typescript": "^4.2.4"
}
}
Create Minimal Server with Express.js and TypeScript
Let’s create what could be considered the most basic server using Express.js. Inside the src
folder, create an index.ts
file and copy the following code:
import express, { Request, Response } from 'express';
const app = express();
const port = 3000;
app.get('/', (req: Request, res: Response) => {
res.send('Hello World!');
});
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
});
As you notice, it will be a simple GET API endpoint returning a message.
Running TypeScript Files in Node.js: Understanding the Process
First, it is important for you to understand the process that happens to run TypeScript files in node.js. Previously, you created a simple server inside the index.ts
. If we were working with plain JavaScript, a similar code could be written in a js
file such as index.js
. Normally, you will run a js
file using the node
command.
node src/index.js
If we try to do something similar with index.ts
file, the terminal will fail due to syntax errors as we are writing code in TypeScript.
// it will fail
node src/index.ts
What we need to do is to compile our TypeScript code into JavaScript code, and we are going to do that using the tsc
command which it is available after installing typescript
dependency in the project.
npx tsc src/index.ts
This will generate an index.js
file. Now that we have our JavaScript file, we can use node
to run our code.
node src/index.js
This will run our server in port 3000. Try opening your browser http://localhost:3000/. You should see a Hello World! message.
We could also set up a tsconfig.json
file. This file is used to determine what all TypeScript files will be compiled in a project. This is useful especially when you want to avoid compiling files containing unit or integration tests. Feel free to checkout for more information about the compilation options available in TypeScript.
Running TypeScript Files in Node.js: Quick Process
There is a package available called ts-node which allows executing our TypeScript file in node
. Therefore, we are going to install ts-node
as part of our development dependencies.
npm i --save-dev ts-node
Once the package is installed, we can run our project with only one command.
npx ts-node src/index.ts
The best thing is that you don’t see any index.js
file generated.
Why using npx
to run ts-node?
At the moment you installed npm
, it came with npx
. This makes it so we have a command to manage dependencies, and another one to execute dependencies.
- npm (package manager)
- npx (package eXecutable)
This gives us the opportunity to execute local dependency files, such as, ts-node
.
If we were to install ts-node
globally like this:
npm i -g ts-node
We could directly execute the ts-node
command.
ts-node src/index.ts
However, this can be problematic especially when working with specific versions of dependencies. The npx
command is also useful when looking to run packages only once and delete them once they are executed. For example, if you try to create a react application using create-react-app
, React’s tutorial recommends using the npx
command.
Setting Up Scripts in the package.json
Now that we understand how to run TypeScript files, we can set up a couple of scripts in the package.json
for our application. We are going to start by setting the start
script in the package.json
file.
"scripts": {
"start": "npx ts-node src/index.ts",
"test": "echo \"Error: no test specified\" && exit 1"
},
Once we save, we can open the terminal and run npm run start
and you will notice our project is running again.
However, we constantly make changes during the development phase, and it turns time-consuming to stop and re-run the project after every change we make to the code base. We are going to install nodemon
.
npm i --save-dev nodemon
Now we can set up another script such as start:watch
to run nodemon
.
"scripts": {
"start:watch": "nodemon src/index.ts",
"start": "npx ts-node src/index.ts",
"test": "echo \"Error: no test specified\" && exit 1"
},
Prior to running npm run start:watch
we need to add an additional configuration. Let’s create another file called nodemon.json
in the root of the project, not inside the src
folder. Once created, assign the following configuration.
{
"watch": "src/**/*.ts",
"execMap": {
"ts": "ts-node"
}
}
This file is the configuration setup at the moment of executing nodemon
. In this case, it will execute ts-node
for any .ts file that is executed using nodemon
.
Now it is time to try our script.
npm run start:watch
You should see your application running. Try making changes to the index.ts
file such as modifying the log generated inside the callback of the listen
function.
console.log(`I just changed this log: http://localhost:${port}`)
Once you save, you should see the updated log in the terminal.
This is the final value for our package.json
of our project.
{
"name": "express-typescript",
"version": "1.0.0",
"description": "Example of using Express with Typescript",
"main": "index.ts",
"scripts": {
"start": "npx ts-node src/index.ts",
"start:watch": "nodemon src/index.ts",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Andrés Reales",
"license": "ISC",
"devDependencies": {
"@types/express": "^4.17.11",
"nodemon": "^2.0.7",
"ts-node": "^9.1.1",
"typescript": "^4.2.4"
},
"dependencies": {
"express": "^4.17.1"
}
}
Setup TypeScript Configuration
The tsconfig.json
file specifies the root files and the compiler options required to compile a TypeScript project. Without it, our TypeScript project would still feel as a JavaScript project because it we are not enforcing the usage of types in our codebase. Therefore, we are going to create a tsconfig.json
in the root folder of our project. Once this is done, add the following configuration:
{
"compilerOptions": {
"module": "commonjs",
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"target": "es6",
"noImplicitAny": true,
"moduleResolution": "node",
"sourceMap": true,
"outDir": "dist",
"baseUrl": ".",
"paths": {
"*": [
"node_modules/*",
"src/types/*"
]
},
},
"include": [
"src/**/*"
]
}
Later on, you can make changes to the configuration based on your project needs. For now, this is a good starting point.
What’s Next?
That’s all for this article, and I’m sure you want to get going with more. In the next section, I will explain How to Set up RESTful API Routing using Express.js with TypeScript.