Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Override res.end with TypeScript

I need to override method res.end with next signature:

res.end = (data: any, encoding: string)

But TS returns next error:

Type '(data: any, encoding: string) => void' is not assignable to type '{ 
(cb?: (() => void) | undefined): void; 
(chunk: any, cb?: (() => void) | undefined): void; 
(chunk: any, encoding: string, cb?: (() => void) | undefined): void; 
}'.ts(2322)

I had tried to pass empty callback, but it have not helped:

res.end = (data: any, encoding: string, callback: `() =>void`): void
like image 336
domanskyi Avatar asked May 10 '19 14:05

domanskyi


2 Answers

Problem

Your initial signature does not pass the compiler check, because the end function, which ServerResponse inherits from stream.Writable, has the following overload:

end(cb?: () => void): void;
end(chunk: any, cb?: () => void): void;
end(chunk: any, encoding: string, cb?: () => void): void;

Since the end function has that overload, the compiler is warning you that, at runtime, you need to check which of the overloads is in use.

Solution

Here is a signature that is type safe. It checks which of the three arguments is the callback and then acts accordingly.

import { Response } from 'express';

const handler = (req: Request, res: Response) => {

  res.end = (arg1: Function | any, arg2?: Function | string, arg3?: Function) => {

    if (typeof arg1 === 'function') {
      // end(cb?: () => void): void;
    }

    if (typeof arg2 === 'function') {
      // end(chunk: any, cb?: () => void): void;
    }

    if (typeof arg3 === 'function') {
      // end(chunk: any, encoding: string, cb?: () => void): void;
    }
  }
};
like image 135
Shaun Luttin Avatar answered Sep 18 '22 08:09

Shaun Luttin


Make your function type to any, this mean it can convert (or assign) to any type.

Try this

res.end = ((data: any, encoding: string): void => { }) as any;

Update

You can make a type what extends express.Response, it overrides end method (the method of NodeJS.WritableStream).

import { Request, Response, Handler } from 'express';

type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>

interface MyResponse extends Omit<Response, "end"> {
  end: (data: any, encoding: string) => void;
}

const handler: Handler = (req: Request, res: MyResponse) => {
  res.end = (data: any, encoding: string) => {

  }
};
like image 31
hoangdv Avatar answered Sep 21 '22 08:09

hoangdv