How to set up an express server with typescript.

Photo by NASA on Unsplash

How to set up an express server with typescript.

When you're developing a server using Node.js and Express, the development experience is usually smooth and efficient. However, additional challenges may arise as your application scales or when collaborating with a globally distributed team of developers. This is where TypeScript can come to the rescue.

In this tutorial, we will explore an approach suitable for beginners to set up TypeScript in an Express application, understanding the underlying limitations and benefits it offers.

To make the most of this tutorial, ensure that you have the following prerequisites:

  • Node.js version ≥ v12.x installed on your local development environment

  • Access to a package manager such as npm or Yarn

  • Basic understanding of Node.js and Express concepts

By following this tutorial, you can leverage TypeScript's advantages in terms of code maintainability, improved collaboration, and catching errors at compile time to enhance your Express development workflow.

Create a package.json file.

Start by creating a new directory wherever you keep your side projects in your local development environment. Inside that directory, use yarn or npm’s initializer command to create a package.json file:

mkdir express-ts
cd express-ts/
yarn init -y

If you prefer npm, then do this:

npm init -y

When you initialize a package.json file, the -y flag uses the default settings you have set up from yarn config. The newly created package.json file might look something like the following code:

{
  "name": "express-typescript",
  "version": "1.0.0",
  "description": "Setting up express server with ts",
  "main": "index.js",
  "scripts": {
    "test": "echo \\"Error: no test specified\\" && exit 1"
  },
  "type": "commonjs",
  "keywords": [],
  "author": "",
  "license": "ISC"
}

Change the "type" in the package.json from module to commonjs.

Install dependencies**.**

After initialising the package.json file, let’s add an Express package. From the terminal window, run the command below:

yarn add express dotenv
npm i express dotenv

Installing TypeScript

We’ll install TypeScript as a development dependency in our project. Additionally, we'll install the @types declaration packages for Express and Node.js, which provide type definitions as declaration files.

Declaration files serve as pre-defined modules that describe the structure and types of JavaScript values for the TypeScript compiler. These declaration files typically have a .d.ts extension and are available for JavaScript libraries that don't natively include TypeScript support.

The official DefinitelyTyped GitHub repository maintains a collection of TypeScript type definitions for various libraries and modules. By leveraging these declaration files, you can avoid manually defining types from scratch.

To install the necessary packages, execute the following command in your terminal:

yarn add -D typescript @types/express @types/node
npm i --save-dev typescript @types/express @types/node

This command will install TypeScript as a development dependency and include the @types declaration packages for Express and Node.js.

By setting up TypeScript and importing the appropriate type definitions, you'll benefit from enhanced code analysis, autocompletion, and catch potential type errors during development in your Express application.

The -D flag, also known as the --dev flag, is a specification for the package manager to install these libraries as devDependencies.

Once these libraries are installed, go to the package.json file where you’ll see a new devDependencies object:

{
"devDependencies": {
"@types/express": "^4.17.17",
"@types/node": "^20.4.2",
"typescript": "^5.1.6"
}
}

Generating tsconfig.json

Now, we have a TypeScript project compiled with some default configuration options. The tsconfig.json file provides these default options and allows us to tweak or customize the compiler options.

Typically, the tsconfig.json file lives at the root of the project. To generate it, we’ll use the tsc command:

npx tsc --init

The command above will generate a new file called tsconfig.json with the following default compiler options:

target: es2016
module: commonjs
strict: true
esModuleInterop: true
skipLibCheck: true
forceConsistentCasingInFileNames: true

If you open the tsconfig.json file, you’ll see many other compiler options that are commented out. In tsconfig.json, compilerOptions is a mandatory field that needs to be specified. The options used in the config above are:

  • target: Allows us to specify the target JavaScript version that the compiler will output

  • module: Allows us to use a module manager in the compiled JavaScript code. CommonJS is supported and is a standard in Node.js

  • strict: An option that enables strict type-checking options

  • esModuleInterop: Allows us to compile ES6 modules to CommonJS modules

  • skipLibCheck: If set to true, skips type-checking of default library declaration files

  • forceConsistentCasingInFileNames: When set to true, enables case sensitive file naming

One option you will have to enable is called outDir, which specifies where the output will be located after the compilation step. You can search for this option in the tsconfig.json file and uncomment it.

By default, the value of this option is set to the root directory. Change it to dist:

{
  "compilerOptions": {
    "outDir": "./dist"

    // rest options remain same
  }
}

If you wish to set a directory as your rootDir , add an additional field besides the compilerOptions , thus the include option.

{
    "compilerOptions": {
        // everthing remains here
    }, 
    "include": ["/src"]
}

After adding include field, let me create the src dir in my root dir.

While there are probably other configuration options you can add to the TypeScript compiler, the options listed above are basic specifications that can help you get started.

Create an Express server with a .ts extension

Now, inside our src dir, let’s create anindex.ts file and create our server.


Open the index.ts file and type this inside it, as shown below:

import express, { Express, Request, Response, NextFunction } from 'express';
import dotenv from 'dotenv';

dotenv.config();

const app: Express = express();
const port = process.env.PORT;

app.get('/', (req: Request, res: Response, next: NextFunction) => {
  res.send('Hello World!!');
});

app.listen(port, () => {
  console.log(`[⚡]: Server is running at <https://localhost>:${port}`);
});

DevDependencies I call helpers.

Another development-related utility library that is very useful when working on Node.js projects is nodemon. nodemon is a tool that helps develop Node.js-based applications by automatically restarting the Node.js application when file changes in the directory are detected.

We’ll also install another dev dependency called Concurrently, which will allow us to run multiple commands like nodemon to watch file changes and the tsc command to compile the code:

yarn add -D concurrently nodemon
npm install -D concurrently nodemon

After installing these dev dependencies, update the scripts in the package.json file:

{
  "scripts": {
    "build": "npx tsc",
    "start": "node dist/index.js",
    "dev": "concurrently \\"npx tsc --watch\\" \\"nodemon -q dist/index.js\\""
  }
}

The build command will compile the code in JavaScript inside a dist directory. The dev command is used to run the Node.js server in development mode.

Now, go back to the terminal window and run npm run dev to trigger the development server:

There are no errors, indicating that the server is successfully running. You can go to the browser window to see the result.

Since nodemon detects changes, you can test it by changing the message sent from res.send() and simultaneously take a look at the terminal to see if nodemon detects any file changes or not:

To compile the code, you need to must command npm run build. There is a new dist directory created after this command executes successfully. Inside this directory, the TypeScript code is compiled to valid JavaScript:

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const express_1 = __importDefault(require("express"));
const dotenv_1 = __importDefault(require("dotenv"));
dotenv_1.default.config();
const app = (0, express_1.default)();
const port = process.env.PORT || 3000;
app.get('/', (req, res, next) => {
    res.send('Hello World!');
});
app.listen(port, () => {
    console.log(`[⚡]Server is running at <http://localhost>:${port}`);
});

If you specify any other directory as the value of the property outDir in the tsconfig.json file, that directory would be reflected here instead of dist.

Conclusion

In conclusion, we have reached the end of this tutorial on building an Express server with TypeScript. I hope you found this guide helpful in understanding how to set up TypeScript in your Node.js and Express backend projects.

TypeScript brings several benefits, including improved code maintainability, enhanced collaboration among team members, and catching potential errors at compile time. While it requires a learning curve and some initial setup, its advantages can be valuable, especially for larger projects or teams.

When deciding whether to use TypeScript in your Node.js and Express projects, carefully consider your application's specific requirements and complexity. TypeScript may be particularly beneficial when you have a large codebase, multiple developers working on the project, or need robust type checking and documentation.

As you continue your journey with TypeScript and Express, I encourage you to explore additional TypeScript features, such as decorators, interfaces, and generics, to enhance your development experience further.

Remember to stay current with the TypeScript and Express communities, as new features and improvements are constantly being introduced. Leverage online resources, official documentation, and community forums to expand your knowledge and tackle any challenges you may encounter.

Thank you for following along with this tutorial. We hope you found it insightful and wish you success in your future endeavours in building express servers with TypeScript!