javascriptnode.jstypescriptmongodbmongoose

TypeScript Error in Express Route: "No Overload Matches This Call"


Question:

I am developing an e-commerce platform using TypeScript with Express. Below is the code snippet and the error I am facing. How can I fix this issue, and why does the solution work?

Code Snippets:

User Router:

router.post('/user/:id/add-address', async (req: Request<IAddress>, res: Response) => {
  try {
    const address = await Address.create(req.body);
    const user = await User.findByIdAndUpdate(
      req.params.id,
      { $push: { address: address._id } },
      { new: true }
    );

    if (!user) {
      return res.status(404).json({
        success: false,
        message: 'User not found'
      });
    }

    return res.status(200).json({ message: 'Address added successfully', user });
  } catch (error) {
    console.error(error);
    return res.status(500).json({ message: 'Error adding address' });
  }
});

Interfaces:

  1. IAddress:
import { Document } from "mongoose";

export default interface IAddress extends Document {
  name?: string;
  lastName?: string;
  email?: string;
  street: string;
  city: string;
  state: string;
  zipcode: number;
  country: string;
  phone: number;
}
  1. IUser:
import mongoose from "mongoose";

export default interface IUser {
  name: string;
  email: string;
  password: string;
  phoneNumber?: string;
  address?: mongoose.Schema.Types.ObjectId[];
  wishlist?: mongoose.Schema.Types.ObjectId[];
  cart?: mongoose.Schema.Types.ObjectId[];
  orderHistory?: mongoose.Schema.Types.ObjectId[];
  paymentMethods?: mongoose.Schema.Types.ObjectId[];
  createdAt?: Date;
  updatedAt?: Date;
}

Error:

No overload matches this call.
  The last overload gave the following error.
    Argument of type '(req: Request<IAddress>, res: Response) => Promise<express.Response<any, Record<string, any>>>' is not assignable to parameter of type 'Application<Record<string, any>>'.
      Type '(req: Request<IAddress, any, any, ParsedQs, Record<string, any>>, res: Response<any, Record<string, any>>) => Promise<...>' is missing the following properties from type 'Application<Record<string, any>>': init, defaultConfiguration, engine, set, and 63 more.ts(2769)
index.d.ts(164, 5): The last overload is declared here.
(parameter) req: express.Request<IAddress, any, any, QueryString.ParsedQs, Record<string, any>>

Solution:

I got the following solution:

router.post('/user/:id/add-address', async (req: Request<IAddress>, res: Response): Promise<any> => {
  // Function logic
});

Question:

Why does adding the explicit Promise<any> type fix the issue? Could you explain the reasoning behind this solution?


Solution

  • Express route handlers and middlewares are expected to return nothing (void type) because the result would be discarded. The support for Promise<void> was added in Express 4 at some point to be compatible with async.

    There should be no return res...:

        if (!user) {
          res.status(404).json(...);
          return;
        }
    
        res.status(200).json(...);
      } catch (error) {
        console.error(error);
        res.status(500).json(...);
      }