3

in typescript, I am trying to overwrite the express's Response json object to be a specific type of object to always be used

for example, I want to enforce a interface type that would error out if the following format was not followed

  return res.status(200).json({
    data: ["a", {"a": "b"}],
    success: true,
  });

I attempted to use dts-gen --m express -f src/types/express.d.ts to create the declaration file to modify but it ended in failure.

is there a way to overwrite a specific type on an existing library or do I need to create a declaration file specific to my needs?

2
  • express is notorious for being not that typeable. It's best to avoid using a lot of custom middleware and to keep well-typed code apart from express routing code, if you choose to keep using this library. Commented Jul 5, 2020 at 17:11
  • good to know, thanks! Commented Jul 5, 2020 at 21:36

3 Answers 3

6
interface Json {
  success: boolean;
  data: any[];
}

type Send<T = Response> = (body?: Json) => T;

interface CustomResponse extends Response {
  json: Send<this>;
}

I was able to create a new interface that extended this. just needed to learn a bit more :) hopefully this can help out someone else!

Sign up to request clarification or add additional context in comments.

2 Comments

missed then add to export const example = asyncHandler(async (req: Request, res: CustomResponse, next: NextFunction) => {
how did you come up with this? which documentation was your reference for these types?
5

You can set custom types in generic types of req and res objects such a:

import type * as E from 'express';

interface CustomResponseType {
  test: string;
}

export default async function Example(
  req: E.Request<undefined, CustomResponseType, [CustomReqBodyType?], [CustomReqQueryType?]>,
  res: E.Response<CustomResponseType>
): Promise<E.Response<CustomResponseType, Record<string, any>>> {
  return res.status(200).json({ test: 'success' });
}

Comments

3

Just an extend reply, if you want to explicit define type for response, you can do like this

// overlap the ResBody = any (from Express module) to the exact type 
// you want in CustomResponse

type Send<ResBody = any, T = Response<ResBody>> = (body?: ResBody) => T;

export interface CustomResponse<T> extends Response {
   json: Send<T, this>
}

then you can import in the controller function:

async (req: Request, res: CustomResponse<IUser>, next: NextFunction) =>

Your res.json() will strictly stick to the IUser Interface.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.