如何在TypeScript中创建适配Express Morgan的Winston日志器?
在TypeScript中创建可记录Express Morgan日志的Winston日志器
我来帮你解决这个TypeScript类型不匹配的问题,其实核心是Morgan的stream选项在TS中有明确的类型约束,咱们一步步来实现正确的配置:
1. 先安装必要依赖
确保你已经安装了核心包和对应的TypeScript类型定义:
npm install express morgan winston npm install -D @types/express @types/morgan @types/winston typescript ts-node
2. 创建Winston日志器实例
先定义一个符合需求的Winston日志器,比如同时输出到控制台和文件:
import winston from 'winston'; const logger = winston.createLogger({ level: 'info', format: winston.format.combine( winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), winston.format.json() ), transports: [ // 控制台输出(带颜色美化) new winston.transports.Console({ format: winston.format.combine( winston.format.colorize(), winston.format.simple() ) }), // 写入到本地日志文件 new winston.transports.File({ filename: 'access.log', level: 'info' }) ] });
3. 适配Morgan的Stream类型(解决类型错误的关键)
Morgan的stream选项要求的是一个带有write方法的对象,在TypeScript中我们可以明确这个对象的类型为Pick<NodeJS.WritableStream, 'write'>,这样就能避免类型不匹配的问题:
import morgan from 'morgan'; // 定义符合Morgan要求的stream对象,仅保留必要的write方法 const morganStream: Pick<NodeJS.WritableStream, 'write'> = { write: (message: string) => { // 去掉Morgan消息末尾的换行符,避免Winston重复输出换行 logger.info(message.trim()); } }; // 创建Morgan中间件,指定使用我们的自定义stream const morganMiddleware = morgan('combined', { stream: morganStream });
4. 在Express中使用中间件
最后把这个Morgan中间件挂载到你的Express应用里:
import express from 'express'; const app = express(); // 挂载日志中间件(要放在路由前面才能捕获所有请求) app.use(morganMiddleware); // 测试路由 app.get('/', (req, res) => { res.send('Hello World!'); }); app.listen(3000, () => { console.log('Server running on port 3000'); });
为什么之前会出现类型错误?
你之前的代码里给Morgan的stream传了一个包含write和logger的对象,但Morgan的类型定义里,stream只接受带有write方法的对象(或者返回ReadableStream的函数),多余的logger属性会触发类型检查错误。上面的代码通过明确morganStream的类型,只保留write方法,完美解决了这个问题。
内容的提问来源于stack exchange,提问作者JoAMoS
相关产品推荐
相关产品推荐

