Reputation: 35
I'm trying to create a custom Express request interface for my API. I do this by creating a custom interface called AuthRequest
which extends Request
from Express. How ever when trying to import my interface and define req
to use that interface I in my middleware function I get the following error from Typescript:
No overload matches this call.
The last overload gave the following error.
Argument of type '(req: AuthRequest, res: Response, next: NextFunction) => void' is not assignable to parameter of type 'PathParams'.
Type '(req: AuthRequest, res: Response<any, Record<string, any>>, next: NextFunction) => void' is missing the following properties from type '(string | RegExp)[]': pop, push, concat, join, and 28 more.ts(2769)
index.d.ts(165, 5): The last overload is declared here.
Project structure:
.
+-- src
| +-- index.ts
| +-- interface.ts
+-- package.json
+-- tsconfig.json
index.ts
import express, { Response, NextFunction } from "express";
import { AuthRequest } from "./interface";
const app = express();
const port = 8080;
app.use((req: AuthRequest, res: Response, next: NextFunction) => {
next();
});
app.listen(port, () => {
console.log(`App started on port ${port}`);
});
interface.ts
import { Request } from "express";
interface User {
id: number;
}
export interface AuthRequest extends Request {
user: User;
}
tsconfig.json
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"outDir": "./dist",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
},
"include": [
"**/*.ts"
],
"exclude": [
"node_modules",
"dist/"
]
}
package.json
{
"name": "ts-express-server",
"version": "1.0.0",
"description": "Typescript Express Server",
"main": "src/index.ts",
"scripts": {
"start": "./node_modules/.bin/tsc --project ./tsconfig.json --watch & ts-node-dev src/index.ts"
},
"dependencies": {
"express": "4.17.1"
},
"devDependencies": {
"ts-node-dev": "1.1.8",
"typescript": "4.4.2",
"@types/express": "4.17.13"
},
"keywords": []
}
Node version: v12.18.4
NPM version: 6.14.13
What am I missing here? Please help!
Upvotes: 0
Views: 3618
Reputation: 1384
This won't work, because Express doesn't know about your AuthRequest class, only Request.
You have two options. The first is to extend the Request object using @types: Extend Express Request object using Typescript
Then you can add user as an optional member. Then you can do the following:
const RequireAuth = (middlewarefn: AuthMiddleware) => (req:Request, res:Response, next:NextFunction) => => {
if(req.user) {
return middlewarefn(req as AuthRequest, res, next)
}
// throw error? 404?
next();
}
You'd have to wrap your authenticated functions but it would give you the signature you need. You are violating the middleware API the way you are doing it, so you need to adapt to your new method signature.
There's a few other ways to approach this from a practical standpoint, if your goal is to ensure that 'user' exists.
Upvotes: 1
Reputation: 360
Instead of extending Request interface, create custom.d.ts and augment existing Request interface.
import { User} from "./interface";
declare module "express-serve-static-core" {
export interface Request {
user?: User;
}
}
If it will not work check answers in following page containing the same problem Extend Express Request object using Typescript
Upvotes: 2