Proper way to extend express Response Object using Typescript

Viewed 2452

I'm currently working on a project that involves Typescript 3+, and express 4+ and node 8+. I'm trying to extend express's Response object to send HTTP status codes if an API detects an error for example. I can't seem to figure out how to extend the Response object without using Middleware to define the Response extended function I want to add. I would love to be able to just use the Response prototype to define the function(s) i want to add but i don't know or can't figure out if this is possible. Here's what I've done:

projectA/declarations/express.extensions.d.ts:

import * as e from "express"

declare global {
    namespace Express {
        interface Response {
            send100(): e.Response;
        }
    }
}

export {}

below is where i would like to define the prototype function definition like so but this isn't compiling...

projectA/extensions/ResponseExtensions.ts

import * as e from "express";
import { Response } from "express-serve-static-core";

Response.prototype.send100 = function(): e.Response {
    var response = this as Response;
    response.status(100).end();
}

and then finally consume...

ProjectB/Server.ts

import * as express from "express"

app.get('/getData'
    request: express.Request, 
    response: express.Response) : void {

    // yada yada...

    response.send100();
}

I can't seem to get the ResponseExtensions.ts script to transpile, And the only other way i see to implement this is to run middleware where i define the function, but this will happen for every single request. Are there options like I'm exploring or is middleware the only way to go?

Thanks.

1 Answers

The Response member of express-serve-static-core is only an interface, not a class with a prototype you can extend, so when you refer to Response as a value, TypeScript resolves it to an unrelated Response class that is part of the DOM API. The prototype object you want to extend is the response member of the express module (see this answer). It isn't declared in @types/express, but you can declare it yourself:

declare module "express" {
    const response: Response;
}

Then in ResponseExtensions.ts, you can write:

import * as e from "express";
import { Response } from "express-serve-static-core";

e.response.send100 = function(): e.Response {
    var response = this as Response;
    response.status(100).end();
}
Related