How to write TypeScript definition for a middleware that adds property to the response?

There's quite a few other Express middlewares you can use as examples, e.g. Method-Override, and its type definitions.

As a more concrete example, if you want to add this .boom property to the response object, you should just need to create a type definition (express-boom.d.ts) containing:

declare namespace Express {
    interface Boom {
        // Add boom's properties in here
    }

    export interface Response {
        boom: Boom
    }
}

Here is a sample usage. Hope this helps someone.

Include express-boom.d.ts along with your applications source files.

Refer the sample-usage.ts in the below gist for example usage:

Gist: Type definitions for express-boom:

express-boom.d.ts

/**
 * Type definitions for express-boom
 * Definitions by: Sandeep K Nair <https://github.com/sandeepsuvit>
 * @author: Sandeep K Nair
 */
declare namespace Express {
    interface Boom {
        // Add boom's properties in here
        wrap: (error: Error, statusCode?: number, message?: string) => BoomError;
        create: (statusCode: number, message?: string, data?: any) => BoomError;

        // 4xx
        badRequest: (message?: string, data?: any) => BoomError;
        unauthorized: (message?: string, scheme?: any, attributes?: any) => BoomError;
        forbidden: (message?: string, data?: any) => BoomError;
        notFound: (message?: string, data?: any) => BoomError;
        methodNotAllowed: (message?: string, data?: any) => BoomError;
        notAcceptable: (message?: string, data?: any) => BoomError;
        proxyAuthRequired: (message?: string, data?: any) => BoomError;
        clientTimeout: (message?: string, data?: any) => BoomError;
        conflict: (message?: string, data?: any) => BoomError;
        resourceGone: (message?: string, data?: any) => BoomError;
        lengthRequired: (message?: string, data?: any) => BoomError;
        preconditionFailed: (message?: string, data?: any) => BoomError;
        entityTooLarge: (message?: string, data?: any) => BoomError;
        uriTooLong: (message?: string, data?: any) => BoomError;
        unsupportedMediaType: (message?: string, data?: any) => BoomError;
        rangeNotSatisfiable: (message?: string, data?: any) => BoomError;
        expectationFailed: (message?: string, data?: any) => BoomError;
        badData: (message?: string, data?: any) => BoomError;
        tooManyRequests: (message?: string, data?: any) => BoomError;

        // 5xx
        notImplemented: (message?: string, data?: any) => BoomError;
        badGateway: (message?: string, data?: any) => BoomError;
        serverTimeout: (message?: string, data?: any) => BoomError;
        gatewayTimeout: (message?: string, data?: any) => BoomError;
        badImplementation: (message?: string, data?: any) => BoomError;
    }

    export interface BoomError {
        data: any;
        reformat: () => void;
        isBoom: boolean;
        isServer: boolean;
        message: string;
        output: Output;
    }

    export interface Output {
        statusCode: number;
        headers: any;
        payload: any;
    }

    export interface Response {
        boom: Boom
    }
}

sample-usage.ts

export function someMiddleware(req: express.Request, res: express.Response, next: express.NextFunction) {
  // use it this way
  res.boom.forbidden("Failed to grant access to resource.");
  next();
}