注册@fastify/middie插件时出现类型匹配错误求助
将Fastify集成到自研小型包中,需通过@fastify/middie使用中间件,但注册middie插件时编辑器抛出类型匹配错误:
No overload matches this call.
Overload 1 of 3, '(plugin: FastifyPluginCallback<FastifyMiddieOptions, Server, FastifyTypeProvider, FastifyBaseLogger>, opts?: FastifyRegisterOptions<...> | undefined): FastifyInstance<...> & PromiseLike<...>', gave the following error.
Argument of type 'FastifyMiddie' is not assignable to parameter of type 'FastifyPluginCallback<FastifyMiddieOptions, Server, FastifyTypeProvider, FastifyBaseLogger>'.
Types of parameters 'instance' and 'instance' are incompatible.
Property 'use' is missing in type 'FastifyInstance<Server, IncomingMessage, ServerResponse, FastifyBaseLogger, FastifyTypeProvider>' but required in type 'FastifyInstance<Server, IncomingMessage, ServerResponse, FastifyLoggerInstance>'.
Overload 2 of 3, '(plugin: FastifyPluginAsync<FastifyMiddieOptions, Server, FastifyTypeProvider, FastifyBaseLogger>, opts?: FastifyRegisterOptions<...> | undefined): FastifyInstance<...> & PromiseLike<...>', gave the following error.
Argument of type 'FastifyMiddie' is not assignable to parameter of type 'FastifyPluginAsync<FastifyMiddieOptions, Server, FastifyTypeProvider, FastifyBaseLogger>'.
Overload 3 of 3, '(plugin: FastifyPluginCallback<FastifyMiddieOptions, Server, FastifyTypeProvider, FastifyBaseLogger> | FastifyPluginAsync<...> | Promise<...> | Promise<...>, opts?: FastifyRegisterOptions<...> | undefined): FastifyInstance<...> & PromiseLike<...>', gave the following error.
Argument of type 'FastifyMiddie' is not assignable to parameter of type 'FastifyPluginCallback<FastifyMiddieOptions, Server, FastifyTypeProvider, FastifyBaseLogger> | FastifyPluginAsync<...> | Promise<...> | Promise<...>'.
Type 'FastifyMiddie' is not assignable to type 'FastifyPluginCallback<FastifyMiddieOptions, Server, FastifyTypeProvider, FastifyBaseLogger>'.
错误提示@fastify/middie未实现use()方法,替换为@fastify/express插件仍出现相同错误,推测是插件注册方式有误。相关代码如下:
import Fastify, { FastifyInstance } from 'fastify'; import Cors from '@fastify/cors'; import Static from '@fastify/static'; import FastifyMiddie from '@fastify/middie'; /** * HttpServer * * The Solidus HttpServer. */ export class HttpServer implements HttpServerInterface { private readonly _rootComponent: Component; private readonly _server: FastifyInstance; private readonly _middleware: Middleware[]; private readonly _config: Configuration; private readonly _corsOptions?: CorsOptions constructor( root: Component, config: Configuration, middleware: Middleware[] = [], cors: CorsOptions|undefined = undefined ) { this._rootComponent = root; this._middleware = middleware; this._config = resolveConfig(config); this._corsOptions = cors; this._server = Fastify({ logger: true }); this._setupServer(); } // other stuff here.... /** * _setupServer() * * _setupServer() sets up the HttpServer. */ private _setupServer(): void { // register middleware if it is defined if (this._middleware.length > 0) { // register middleware. // this line is throwing the error. this._server.register(FastifyMiddie, { hook: 'preHandle' }); this._middleware.forEach(middleware => this._server.use(middleware)); } // set up cors if it is enabled. if (this._corsOptions) { this._server.register(Cors, { // cors settings. allowedHeaders: this._corsOptions?.allowHeaders, credentials: this._corsOptions.credentials, exposedHeaders: this._corsOptions.exposeHeaders, hideOptionsRoute: this._corsOptions.hideOptionsRoute, maxAge: this._corsOptions.maxAge, methods: this._corsOptions.methods, optionsSuccessStatus: this._corsOptions.optionsSuccessStatus, origin: this._corsOptions.origin, preflight: this._corsOptions.preflight, preflightContinue: this._corsOptions.preflightContinue, strictPreflight: this._corsOptions.strictPreflight }); } // register public path. this._server.register(Static, { root: join(process.cwd(), '/dist/public'), }); // register the error handler this._server.setErrorHandler((error, req, res) => { this._server.log.error(error.message); res.status(500).send('Server Error'); }); // register the main route. this._server.get('*', async (req, res) => { const tags: TagDescription[] = [] const App = this._configureRootComponent(this._rootComponent, req.url, req.ip, tags); if (this._config.ssr! === 'stream') { renderToStream(() => <App />).pipe(res.raw); } else { let page: string; try { if (this._config.ssr! === 'async') { page = await renderToStringAsync(() => <App />); } else { page = renderToString(() => <App />); } res .status(200) .header('Content-Type', 'text/html') .send(this._configureResponse(page, tags)); } catch (e) { this._server.log.error((e as Error).message); res.status(500).send("Server Error"); } } }); } }
1. 导入middie类型扩展,修正TypeScript类型识别
注册@fastify/middie后,Fastify实例会新增use方法,但默认的FastifyInstance类型不包含该方法。需要导入middie提供的类型扩展文件:
import Fastify, { FastifyInstance } from 'fastify'; // 新增该行,扩展FastifyInstance类型以包含use方法 import '@fastify/middie'; import Cors from '@fastify/cors'; import Static from '@fastify/static'; import FastifyMiddie from '@fastify/middie';
2. 处理插件注册的异步流程
Fastify的register是异步操作,同步调用后立即使用use方法会导致类型未及时更新,同时存在运行时风险。需修改代码保证异步流程正确:
constructor( root: Component, config: Configuration, middleware: Middleware[] = [], cors: CorsOptions|undefined = undefined ) { this._rootComponent = root; this._middleware = middleware; this._config = resolveConfig(config); this._corsOptions = cors; this._server = Fastify({ logger: true }); // 用立即执行异步函数处理构造函数中的异步逻辑 (async () => { await this._setupServer(); })(); } // 将_setupServer改为异步方法 private async _setupServer(): Promise<void> { if (this._middleware.length > 0) { // 等待middie插件注册完成 await this._server.register(FastifyMiddie, { hook: 'preHandle' }); this._middleware.forEach(middleware => this._server.use(middleware)); } // 其余插件注册也建议使用await,保证执行顺序和类型正确 if (this._corsOptions) { await this._server.register(Cors, { allowedHeaders: this._corsOptions?.allowHeaders, credentials: this._corsOptions.credentials, exposedHeaders: this._corsOptions.exposeHeaders, hideOptionsRoute: this._corsOptions.hideOptionsRoute, maxAge: this._corsOptions.maxAge, methods: this._corsOptions.methods, optionsSuccessStatus: this._corsOptions.optionsSuccessStatus, origin: this._corsOptions.origin, preflight: this._corsOptions.preflight, preflightContinue: this._corsOptions.preflightContinue, strictPreflight: this._corsOptions.strictPreflight }); } await this._server.register(Static, { root: join(process.cwd(), '/dist/public'), }); // 错误处理和路由注册无需await,可保留原有逻辑 this._server.setErrorHandler((error, req, res) => { this._server.log.error(error.message); res.status(500).send('Server Error'); }); this._server.get('*', async (req, res) => { const tags: TagDescription[] = [] const App = this._configureRootComponent(this._rootComponent, req.url, req.ip, tags); if (this._config.ssr! === 'stream') { renderToStream(() => <App />).pipe(res.raw); } else { let page: string; try { if (this._config.ssr! === 'async') { page = await renderToStringAsync(() => <App />); } else { page = renderToString(() => <App />); } res .status(200) .header('Content-Type', 'text/html') .send(this._configureResponse(page, tags)); } catch (e) { this._server.log.error((e as Error).message); res.status(500).send("Server Error"); } } }); }
3. 可选:直接创建支持middie的Fastify实例
另一种简化方式是在创建Fastify实例时直接启用middie,无需手动注册插件,TypeScript会自动识别use方法:
this._server = Fastify({ logger: true, // 直接传入middie插件,实例创建时自动启用 plugin: FastifyMiddie });
内容的提问来源于stack exchange,提问作者Patrick Lumenus

