匿名require语句的TypeScript类型定义及Express中间件注册问题
First, ensure you have the essential TypeScript type definitions for Express installed. Run this in your project root:
npm install --save-dev @types/express @types/node
Option 1: Direct Type Casting for require Calls
If you prefer to keep using require statements, you can explicitly cast each imported route to express.Router to give TypeScript the context it needs. First, make sure you’ve imported Express at the top of your server file:
import express from 'express'; const app = express(); // Import your access control instance (adjust the path as needed) import ac from './path-to-your-access-control-module';
Then update each app.use line with a type cast to eliminate anonymous type errors:
app.use('/api/v1/seed_db', ac.allow('ROLE_ADMIN'), require('./routes/seed-db') as express.Router); app.use('/api/v1/email', require('./routes/email') as express.Router); app.use('/api/v1/changelog', require('./routes/changelog') as express.Router); app.use('/api/v1/acquisitions', require('./routes/acquisitions') as express.Router); app.use('/api/v1/assignments', require('./routes/assignments') as express.Router); app.use('/api/v1/caches', require('./routes/caches') as express.Router); app.use('/api/v1/comments', require('./routes/comments') as express.Router);
Option 2: Switch to ES Module Imports (More Idiomatic for TypeScript)
For a cleaner, maintainable approach, replace require calls with ES module imports. First, ensure each route file exports an Express Router as its default export. For example, in ./routes/seed-db.ts:
import express from 'express'; const router = express.Router(); // Define your route handlers here router.post('/', (req, res) => { // Your database seeding logic res.status(200).json({ message: 'Database seeded successfully' }); }); export default router;
Then in your server file, import each router explicitly—TypeScript will automatically infer the correct type:
import express from 'express'; const app = express(); import ac from './path-to-your-access-control-module'; // Import route routers import seedDbRouter from './routes/seed-db'; import emailRouter from './routes/email'; import changelogRouter from './routes/changelog'; import acquisitionsRouter from './routes/acquisitions'; import assignmentsRouter from './routes/assignments'; import cachesRouter from './routes/caches'; import commentsRouter from './routes/comments'; // Register middleware and routes app.use('/api/v1/seed_db', ac.allow('ROLE_ADMIN'), seedDbRouter); app.use('/api/v1/email', emailRouter); app.use('/api/v1/changelog', changelogRouter); app.use('/api/v1/acquisitions', acquisitionsRouter); app.use('/api/v1/assignments', assignmentsRouter); app.use('/api/v1/caches', cachesRouter); app.use('/api/v1/comments', commentsRouter);
Typing Custom Middleware (Like ac.allow)
If your access control middleware (ac.allow) doesn’t already have TypeScript types, define a type for it to ensure it’s compatible with Express middleware:
import express from 'express'; // Define the type for your access control function type AccessControlAllowFn = (role: string) => express.RequestHandler; // Type your access control instance const ac: { allow: AccessControlAllowFn } = { allow: (role) => (req, res, next) => { // Your access control logic here if (req.user?.roles.includes(role)) { next(); } else { res.status(403).json({ message: 'Forbidden' }); } } }; export default ac;
This tells TypeScript that ac.allow returns a valid Express request handler, preventing type errors when using it in app.use.
内容的提问来源于stack exchange,提问作者Alexander Mills

