Type not being checked in custom response structure in Express

Issue

I am starting of with typescript and have hit a roadblock where I can’t figure out why types are not being validated.

Route

app.use((req: Request, res: Response) => {
  // here 404 is a string but should be a number according to type defined but no error is shown
  return res.error({ status: '404', message: 'The API route does not exist' })
})

Middleware

interface APIResponse {
  status: number,
  message?: string | null,
  data?: any
}

const responseHelper = (req: Request, res: Response, next: NextFunction) => {
  res.showDefaultErrorPage = (status: number = 500) => {
      //...
  }

  res.success = (options: APIResponse) => {
    const {
      status = 200,
      message = null,
      data
    } = options

    //...
  }

  res.error = (options: APIResponse) => {
    const {
      status = 500,
      message = null
    } = options

    //...
  }

  next()
}

export default responseHelper

Custom type definition for express response

/* eslint-disable no-unused-vars */
declare namespace Express {
  interface Response {
    showDefaultErrorPage?: any
    showErrorPage?: any
    success?: any
    error?: any
  }
}

Solution

You could change your type definiton to this:

import express from "express" 
const app = express()


interface APIResponse {
  status: number,
  message?: string | null,
  data?: any
}

// add "declare global" here
declare global {
  namespace Express {
    interface Response<
      ResBody = any,
      Locals extends Record<string, any> = Record<string, any>,
      StatusCode extends number = number
    > {
      showDefaultErrorPage?: any
      showErrorPage?: any
      success: (options: APIResponse) => Response<any, Record<string, any>, number>
      error: (options: APIResponse) => Response<any, Record<string, any>, number>
    }
  }
}

// Dont give explicit types here. Let TypeScript infer them
app.use((req, res, next) => {

  res.showDefaultErrorPage = (status: number = 500) => {
      //...
  }

  res.success = (options: APIResponse) => {
    const {
      status = 200,
      message = null,
      data
    } = options

    return res.status(0).json({})
  }

  res.error = (options: APIResponse) => {
    const {
      status = 500,
      message = null
    } = options

    return res.status(0).json({})
  }

  next()
})

// Dont give explicit types here 
app.use((req, res) => {
  return res.error({ status: '404', message: 'The API route does not exist' })
  //                 ^^^^^^ Expected error
})

Answered By – Tobias S.

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published