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の期待動作を一致させられます。型定義のダウングレードは一時的な回避策として有効ですが、根本的な解決ではありません。