0

const app = express();

This block is working when I use type any for response object

app.use((_req: Request, response: any, next: NextFunction) => {
    response.success = function ({ result = {}, code = 200, message = "" }) {
        return response.json({
            result, code, message
        })
    }
    next();
})

This block is not working when I use Response type from express because the property success does not exist.

app.use((_req: Request, response: Response, next: NextFunction) => {
    response.success = function ({ result = {}, code = 200, message = "" }) {
        return response.json({
            result, code, message
        })
    }
    next();
})

So I create a new type CustomResponse

interface BaseParams {
    code?: number,
    message?: string,
    result?: any
}

interface CustomResponse extends Response {
    success: (params: BaseParams) => Response;
};

app.use((_req: Request, response: CustomResponse, next: NextFunction) => {
    response.success = function ({ result = {}, code = 200, message = "" }) {
        return response.json({
            result, code, message
        })
    }
    next();
})

I get this new error

No overload matches this call.
The last overload gave the following error.
Argument of type '(_req: Request, response: CustomResponse, next: NextFunction) => void' is not assignable to parameter of type 'PathParams'

So I wonder how can I create this kind of global methods using typescript in the right way to avoid this PathParams error type

  • No TS expert hey, but have you tried `Object.defineProperty`? – code Aug 07 '22 at 02:56
  • It seems like the error disappears but there is no autocompletion of the new method. – GianPierre Gálvez Aug 07 '22 at 04:11
  • Alright, does it give you the desired result? – code Aug 07 '22 at 05:18
  • Nope because when I tried to use the method that I added with Object.definProperty appears an error that this property does not exist on Response type – GianPierre Gálvez Aug 08 '22 at 02:00
  • Well, then unfortunately I don't believe this is possible. I don't see why you have to extend `response` though: why not just `response.json({ result, code, message });`? – code Aug 08 '22 at 02:40
  • I would like to create standard methods for responses for success and errors :'( , this way works on node without ts I have seen the example but with ts I think is a little bit more difficult – GianPierre Gálvez Aug 14 '22 at 02:24
  • 1
    Hmm, I believe I've found the solution: [Extend Express Request object using Typescript](https://stackoverflow.com/questions/37377731/extend-express-request-object-using-typescript) – code Aug 14 '22 at 21:27
  • Thank you both, the example was on the Request object but I could replicated on Response. I will post how I achieved the fix with the example that you linked in. – GianPierre Gálvez Aug 15 '22 at 17:37

1 Answers1

0

I created the types/express/index.d.ts file

interface BaseParams {
    code?: number,
    data?: any,
    errors?: any,
    message?: string,
}

declare namespace Express {
    interface Request {
        user?: any;
    }
    interface Response {
        onSuccess: (params: BaseParams) => Response;
        onError: (params: BaseParams) => Response;
    }
}

Then I edited my tsconfig.json with

"compilersOptions": {
   "typeRoots": ["./types"],
}

So I can add extra fields that I needed on Response or Request types. On my routes file

const router = Router();
router.use((_req, response: Response, next: NextFunction) => {
    response.onSuccess = ({ data = {}, code = HTTPStatus.OK, message = "" }) => {
        return response.status(code).json({
            statusCode: code,
            message,
            data
        })
    }
    response.onError = ({ errors = {}, code = HTTPStatus.BAD_REQUEST, message = "" }) => {
        return response.status(code).json({
            statusCode: code,
            message,
            errors
        })
    }
    next();
});