DEV Community

Joe Flateau
Joe Flateau

Posted on • Originally published at joeflateau.net on

Extending express request/response objects in Typescript

It’s useful to be able to provide a unified response “envelope” when creating a REST API. This envelope can contain metadata, data and information on errors and warnings.

To do so with express for nodejs you can add custom functions to the request prototype and declare them in a module augmentation.

import { response } from "express";

// augment the `express-serve-static-core` module
declare module "express-serve-static-core" {
  // first, declare that we are adding a method to `Response` (the interface)
  export interface Response {
    respondWithData(data: any): this;
  }
}

// now actually add it to `response` (the prototype)
response.respondWithData = function(data) {
  return this.json({ errors: null, data: data });
};

Possibly confusing:

The value request imported from express refers is the prototype of request objects passed to handler functions; it implements the Request interface exported by express-static-serve-core

The interface Request imported from express-static-serve-core refers to a Typescript interface and has no runtime meaning

After we’ve declared the method and added it to the prototype, we can now call it from our route handler:

app.get("/foo", async(req, res) => {
  res.respondWithData({ success: true });
});

Top comments (3)

Collapse
 
hosseinnedaee profile image
Hossein Nedaee

thanks, useful
where should we put these extends? I mean a filelike custom.d.ts and add then how to add it to tsconfig.json

Collapse
 
joeflateau profile image
Joe Flateau

Hossein, you don't have to put it in a *.d.ts or touch tsconfig.json at all. Just put the declare module "foo" {} in the .ts file where you also patch the new method in and you'll be 👌

Collapse
 
hosseinnedaee profile image
Hossein Nedaee

Thanks Joe.