Express.jsで発生する「No overload matches this call」TypeScriptエラーの解決策
問題の発生原因
Express.jsアプリケーションでルートハンドラーを定義する際、以下のTypeScriptエラーが発生します:
No overload matches this call.
Argument of type '(req: Request, res: Response) ⇒ Promise<...>'
is not assignable to parameter of type 'Application<Record<string, any>>'.このエラーの主な原因は:
- ルートハンドラーが
resオブジェクトを返却しようとしている - TypeScriptの型システムとExpressの関数シグネチャの不一致
- 非同期ハンドラー(
async)における戻り値型の扱いの違い
Expressの型定義では、ルートハンドラーは**値を返さない(void)**ことが期待されています。しかしasync関数は常にPromiseを返すため、型システムが矛盾を検出しています。
解決方法
以下のいずれかの方法で問題を解決できます:
✅ 方法1: レスポンス後に明示的にreturnする(推奨)
レスポンス送信後にreturn;で関数を終了します:
router.post('/create-checkout-session', async (req: Request, res: Response) => {
if (!validUser(req)) {
res.status(400).send({ message: 'Invalid user' });
return; // 戻り値なしで終了
}
// 正常処理続行
});✅ 方法2: void演算子を使用する
レスポンスの発行部分をvoidで明示的に未評価にします:
router.post('/create-checkout-session', async (req: Request, res: Response) => {
if (errorCondition) {
void res.status(401).json({ error: 'Unauthorized' });
return;
}
// 正常処理
});⚠️ 方法3: 型定義のダウングレード(一時的対策)
根本的な解決ではありませんが、一時的な回避策として@types/expressをv4にダウングレード:
npm install -D @types/express@4なぜこれが解決策なのか
戻り値の矛盾解消
Expressはルートハンドラーで戻り値を受け取りません → 明示的なreturnでvoidを返す型システムとランタイムの整合
async関数のPromise戻り値とExpressのvoid期待を整合させるリクエスト処理フローの明確化
レスポンス後に処理を継続しないことをコードで明示
補足アドバイス
エラーハンドリングのベストプラクティス
一貫したエラーレスポンス構造を使用:tsif (error) { res.status(400).json({ error: 'Bad Request', details: error.message }); return; }ミドルウェアでの統一処理
認証チェックなどは専用ミドルウェアに分離:ts// 認証ミドルウェア const authMiddleware = (req: Request, res: Response, next: NextFunction) => { if (!req.user) return res.status(401).send('Unauthorized'); next(); }; // ルート適用 router.post('/create-checkout-session', authMiddleware, async (req, res) => { ... });型定義バージョンの確認
パッケージの整合性を確認:json"devDependencies": { "@types/express": "^4.17.21", "express": "^4.18.3" }
まとめ
No overload matches this callエラーは、Expressのルートハンドラーで誤ってresオブジェクトを返そうとする際に発生します。res操作後に戻り値のないreturnを明示することで、TypeScriptの型システムとExpressの期待動作を一致させられます。型定義のダウングレードは一時的な回避策として有効ですが、根本的な解決ではありません。