In this article we are going to learn about how to setup an express js server with typescript
here is what we are going to learn in this article
- Prerequisites
- Setting Up your project
- Initializing a new Node Project
- Installing TypeScript with Express
- Configuring TypeScript with Express
- Structuring your TypeScript Express App
- Project Structure Best Practices
- Creating Modular Routes with Express and TypeScript
- Implementing Middleware in TypeScript
Prerequisites
Here are some of the prerequisites that you need to know and software that you need to install in your system
- NodeJs and NPM
- Basic Familiarity with Express and TypeScript
- Good to have: VSCode and Postman
Setting up your Project
Here is a quick guide on how to set up your project and quickly set up and running your application
- Create a new project directory
mkdir sample-express-typescript-app
cd sample-express-typescript-app
2. Init the project with npm
npm init
npm init will ask you several questions and you can specify the answer to these as you wish.
Once you create the project open it in VScode there you will see a package.json file open it
3. package.json file details
In the package.json file you will see a JSON object that contains all the project dependencies of your project
It will list all the node packages that your project depends on. As you install more and more packages they will be listed here
the package.json file looks something like this
Installing TypeScript and Express
Commands to install TypeScript, Express, and essential typing dependencies.
Here is how you can install typescript and expres to your project. You will see then added as dependencies in your package.json file as well
next install the type definitions for express and node js modules
Setting up tsconfig.json for TypeScript configuration and explaining key options for Node.js projects.
We have installed typescript and express, we need to create the typescript configuration file. The config file specifies the root files and the compiler options.
You can generate a basic config file by running the following command
npx tsc --init
Here are some of the important options that are relevant to any node js project
- target: You can set the ECMA script target with this flag, you can set it to ECMA 2016 or ECMA 6 script
- module: You can configure the module with this. For Our project we are using common JS
- rootDir: This specifies the root directory of the project. For our project we are using the
src
directory as our root directory - outDir: This specifies the directory where the compiled files will be stored. We are setting this to ./dist directory for our project
- strict: You can set it to true for strict type check or let it to false for milder type checking
- esModuleInterop: If you are working with ES modules in typescript then it is recommended to set it to true as it will then enable compatibility with Babel module.
- skipLibCheck: This will cause the type script to skip checking of declaration files if checked as true.
Let us look at a common example of a generated tscofig.json file. This is a compressed version. If you want to look at the complete generated file I have attached it at the bottom of this article
Configuring typescript with express
Creating a basic express server in typescript
In this section we are going to create a basic server with express and typescript.
we have already initialized a new project and installed typescript and express as dependencies and we have also created a tsconfig.json
file
- Open the
tsconfig.json
file and set these properties
"target": "ES6"
: Set the ECMA script version"module": "commonjs"
: We are using CommonJS module resolution."outDir": "./dist"
:We are setting the ./dist as owr complied code directory."rootDir": "./src"
: we are setting our root directory to be ./src"strict": true
: We are enabling strict type checking"esModuleInterop": true
: We are setting the ES Modules to compile with Common JS
Now create a src
directory that would hold all your typescript files in it and create a app.ts file which will be our entry point
and a dist directory that will store the compiled files. here are all the files
./dist/app.js
This is a compiled file. You do not need to do anything here
./src/app.ts
package.json
tsconfig.json
to start the server run the below command
Now, go to localhost://3000 and you can see the server running
Detailed explanation of TypeScript types and interfaces to enhance Express server development.
In this section we are going to learn more about the typescript types and interfaces
- Primitive types: The basic types are called as primitive types in typescript
- Any and Unknown:
Any
allows for any type and hense should be used rarely because it bypasses the type checking of typescript.unknown
is a better alternative because the typescript first tries to check the type and then perform any operation on the variables - Union and intersection types: Union type that is for example
string | number
allows the variable to be one of several types. Intersection types combine many types into one, this ensures that the variable meets all the creteria and is useful for combining interfaces - Custom types: These are useful for combining complex types in request and response object for express servers. the custom tyoes can be defined using the
type
structure
TypeScript Interfaces
- function types: You can define function types with the help of typescript interfaces, this can be useful in creating express middleware or route handlers and reuse of type definations.
- extending interfaces: Interfaces can extend to one or multiple interfaces. This could be useful in creating complex data structures and sharing common properties amoung those complex data structures
- Implementing interfaces: Classes in typescript can implement interfaces, to make sure that the class adhere to specific structure. You can use these to define service classes or controllers in an express application
Typescript type system is beneficial in express server applications, because of the following reasons
- Enhanced code quality and understandability
- Error Reduction
Here is how you can use TypeScript types and interfaces in your express app
- Defining Custom interfaces for Req Bodies
- Using Types for Route Handlers
- Middleware with TypeScript
Structuring your TypeScript Express Application
Project Structure Best Practices
- Separation of concerns: Organize your project such that each module or component is responsible for a single aspect of the application
- use a modular approach for routes: Make your routes easy to manage and handle by grouping your route handlers into separate modules based on their domain or files
- Centralized configuration: Simplify your configuration management by keeping your app config in a centralized location. This also makes your
- Encapsulate database operations: Place the data modules and database acceess login in separate locations, this makes code cleaner and more maintainable
- Implement Middleware cognizantly: Organize middleware functions that handle errors , log request and parse request body in a seprate directory this will help in reusing these routes and functions and thus making the code clearner and more maintainable
- Use TypeScript Features: Use typescript features such as type safety and other features to make code better
- Env Config : Store env variables in a seprate file in the root directory called the .env file this keeps your sensitive information from the GIT or any other version control system that you might be using
Here is a sample direct
here we have a
Creating Modular Routes with Express and TypeScript
Step by step guide to creating Modular Routes
- Setting Up the project with TypeScript:
Ensure that you have initialized a typescript project and are using express with it.
- Creating a Router Module
- Define a Router file:
Create a router file that will have all the routes related to a particular subject. For example if you are building user related routes you might have a file named userRoutes.ts
inside the routes folder
- Import dependencies
Import the express js and any other dependencies that you might have in your project
- Create and Configure the Router Module
- Use express.router() method to create a router instance and then define route handlers using the instance
const router = express.Router();
router.get('/', (req: Request, res: Response) => {
res.send('A group of users');
});
router.post('/', (req: Request, res: Response) => {
const newUser = req.body;
res.status(201).send(newUser);
});
- Export the router:
Make sure that you are exporting the router instance at the end of the page so that it can be imported elsewhere it is needed
export default router;
- Mounting Router in your express
You can use the app.use
to mount the router in your application in the app.js file which is the main application file.
import express from 'express';
import userRouter from './routes/userRoutes';
const app = express();
const PORT = 3000;
app.use(express.json()); // you can parse JSON file with this
// Mounting the router on the users path
app.use('/users', userRouter);
app.listen(PORT, () => {
console.log(`Server running on http://localhost:${PORT}`);
});
Implementing Middleware in TypeScript
By implementing middleware in typescript, we can use the strong type safety features of typescript with our middleware and ensure code readability and maintainability
Middleware basically handles the req, res and next functions in your express js application. You can use middleware for logging, error handling and request validation tasks as well as the traditional handling of req, res and next tasks
Writing custom middleware in typescript
Middleware functions in express have access to the req Object. these functions handle req , res and next functions. The middleware function is the next function in the application req, res cycle
the next middleware function is commonly denoted with the next variable
- Logging Middleware
You can create a simple middleware function to log details about the req, response cycle to the console and this can help with debugging and monitoring
import { Request, Response, NextFunction } from 'express';
const loggerMiddleware = (req: Request, res: Response, next: NextFunction): void => {
console.log(`${req.method} ${req.path}`);
next();
};
In the above example the request response and nextfunction are typescript types which ensures that the arguments are correctly typed
- Error Handling middleware
Error handling is a bit more complex than logging, because it needs to catch errors from the previous middlewar function.
The error handling middleware takes four objects, along with the usual req, res and next it also takes an error object
- Request Validation Middleware
If you want to do request validation for example to ensure that in a POST request the oncoming data conforms to expected schema. You can use libraries like joi and @hapi/joi along with the typescript to provide powerful data validation along with type safety
import { Request, Response, NextFunction } from 'express';
import Joi from 'joi';
const userSchema = Joi.object({
username: Joi.string().required(),
password: Joi.string().min(6).required()
});
const validateUser = (req: Request, res: Response, next: NextFunction): void => {
const { error } = userSchema.validate(req.body);
if (error) {
res.status(400).send(error.details[0].message);
} else {
next();
}
};
In this above schema the joi is defining the expected schema class of the request body. The middleware validates the oncoming data with this schema class and if valied forwards it or returns an error
Utilizing Middleware in your application
You can use the middleware in your application like so
import express from 'express';
const app = express();
app.use(loggerMiddleware); // here we are using logger middleware globally
app.use('/api/users', validateUser, userRoutes); //here we are using the validation middleware for soome specific routes
app.use(errorHandler); // here we are using the Error handling middleware. It should be used the last, after all other middleware and routes
const PORT = 3000;
app.listen(PORT, () => console.log(`Server running on http://localhost:${PORT}`));
implementing middleware with typescript not only adds type safety, it also improves the code readability and maintainability.
In conclusion, this is how you can safely use typescript with your express app
Need Chat API for your website or app
DeadSimpleChat is an Chat API provider
- Add Scalable Chat to your app in minutes
- 10 Million Online Concurrent users
- 99.999% Uptime
- Moderation features
- 1-1 Chat
- Group Chat
- Fully Customizable
- Chat API and SDK
- Pre-Built Chat
Metered TURN servers
- Global Geo-Location targeting: Automatically directs traffic to the nearest servers, for lowest possible latency and highest quality performance. less than 50 ms latency anywhere around the world
- Servers in 12 Regions of the world: Toronto, Miami, San Francisco, Amsterdam, London, Frankfurt, Bangalore, Singapore,Sydney, Seoul
- Low Latency: less than 50 ms latency, anywhere across the world.
- Cost-Effective: pay-as-you-go pricing with bandwidth and volume discounts available.
- Easy Administration: Get usage logs, emails when accounts reach threshold limits, billing records and email and phone support.
- Standards Compliant: Conforms to RFCs 5389, 5769, 5780, 5766, 6062, 6156, 5245, 5768, 6336, 6544, 5928 over UDP, TCP, TLS, and DTLS.
- Multi‑Tenancy: Create multiple credentials and separate the usage by customer, or different apps. Get Usage logs, billing records and threshold alerts.
- Enterprise Reliability: 99.999% Uptime with SLA.
- Enterprise Scale: With no limit on concurrent traffic or total traffic. Metered TURN Servers provide Enterprise Scalability
- 50 GB/mo Free: Get 50 GB every month free TURN server usage with the Free Plan
- Runs on port 80 and 443
- Support TURNS + SSL to allow connections through deep packet inspection firewalls.
- Support STUN
- Supports both TCP and UDP
Generated tsconfig.json
file