How to add Typescript definitions to Express req & res How to add Typescript definitions to Express req & res express express

How to add Typescript definitions to Express req & res


You can use ES6 style named imports to import only the interfaces you need, rather than import * as express from 'express' which would include express itself.

First, make sure you have installed the type definitions for express (npm install -D @types/express).

Example:

// middleware/authCheck.tsimport { Request, Response, NextFunction } from 'express';export const authCheckMiddleware = (req: Request, res: Response, next: NextFunction) => {  ...};// server.tsimport { authCheckMiddleware } from './middleware/authCheck';app.use('/api', authCheckMiddleware);

Currently using TypeScript 2.3.4 and @types/express 4.0.36.


It can be daunting to type the arguments every time you need to write middleware functions so you can just type the whole function directly too.

npm i @types/express --save-dev ("@types/express": "^4.17.0")

After installing typings..

// This can be shortened..import { Request, Response, NextFunction } from 'express';export const myMiddleware = (req: Request, res: Response, next: NextFunction) => {  ...};// to this..import { RequestHandler } from 'express';export const myMiddleware: RequestHandler = (req, res, next) => {  ...};// or in case it handles the error objectimport { ErrorRequestHandler } from 'express';export const myMiddleware: ErrorRequestHandler = (err, req, res, next) => {  ...};


What I've found is that you can leverage TypeScript generics very effectively to create a wrapper around the Express Request type.

You can declare something that looks similar to this in an interfaces file/folder:

import { NextFunction, Request, Response } from 'express';type TypedRequest<  ReqBody = Record<string, unknown>,  QueryString = Record<string, unknown>> = Request<  Record<string, unknown>,  Record<string, unknown>,  Partial<ReqBody>,  Partial<QueryString>>;export type ExpressMiddleware<  ReqBody = Record<string, unknown>,  Res = Record<string, unknown>,  QueryString = Record<string, unknown>> = (  req: TypedRequest<ReqBody, QueryString>,  res: Response<Res>,  next: NextFunction) => Promise<void> | void;

TypedRequest is effectively a wrapper around Express' Request interface, and populates it with the generics that you pass it, but are also optional (note Record<string, unknown>. It then also applies a Partial around each of the generics (you probably want to make this a DeepPartial instead)

ExpressMiddleware takes in 3 optional generics ReqBody Res and QueryString. These are used to construct a function signature that resembles what middlewares/controllers should look like.

The above then allows you to strongly type & consume as follows:

import { ExpressMiddleware } from '../interfaces/ExpressMiddleware';type Req = { email: string; password: string };type Res = { message: string };export const signupUser: ExpressMiddleware<Req, Res> = async (req, res) => {  /* strongly typed `req.body`. yay autocomplete 🎉 */  res.json({ message: 'you have signed up' }) // strongly typed response obj};

I hope this helps someone. It's made a massive difference to my Express experience.