如何在Fastify不同插件中实现装饰器的独立作用域类型定义?
实现Fastify插件作用域独立的类型定义
要解决全局类型扩展导致跨作用域属性可访问的问题,你可以通过泛型约束插件实例类型的方式,为每个插件作用域定义独立的类型,具体做法如下:
步骤1:为每个插件定义专属的扩展类型
通过交叉类型,给每个插件的Fastify实例添加专属的装饰属性类型:
import Fastify, { FastifyInstance, FastifyPluginCallback } from 'fastify'; const fastify = Fastify(); // 作用域A的专属实例类型:基础FastifyInstance + utilA属性 type FastifyInstanceA = FastifyInstance & { utilA: string; }; // 作用域B的专属实例类型:基础FastifyInstance + utilB属性 type FastifyInstanceB = FastifyInstance & { utilB: () => string; };
步骤2:用泛型约束插件的实例类型
使用FastifyPluginCallback的第三个泛型参数,指定当前插件的实例类型,这样插件内部的instance会被严格约束为专属类型:
作用域A插件
const pluginA: FastifyPluginCallback<{}, {}, FastifyInstanceA> = (instance, opts, done) => { // 装饰属性,类型自动匹配FastifyInstanceA的定义 instance.decorate('utilA', 'AAA'); instance.get('/', (req, reply) => { const data = instance.utilA; // 类型正常,无报错 // 如果尝试访问instance.utilB,TypeScript会直接报错(FastifyInstanceA中无此属性) reply.send(data); }); done(); }; fastify.register(pluginA, { prefix: '/A/' });
作用域B插件
const pluginB: FastifyPluginCallback<{}, {}, FastifyInstanceB> = (instance, opts, done) => { instance.decorate('utilB', () => 'BBB'); instance.get('/', (req, reply) => { const data = instance.utilB(); // 类型正常,无报错 // 尝试访问instance.utilA会触发类型错误 reply.send(data); }); done(); }; fastify.register(pluginB, { prefix: '/B/' });
为什么这个方案有效
通过泛型将插件的实例类型限定为专属的扩展类型,TypeScript会在编译阶段严格检查插件内部的属性访问:
- 每个插件只能访问自己装饰的属性
- 跨作用域访问不属于当前插件的属性会直接触发类型错误
- 不会像全局模块扩展那样污染整个FastifyInstance类型
拆分文件的场景优化
如果你的插件拆分在不同文件中,也可以在每个插件文件内部定义专属类型,避免全局污染:
比如plugin-a.ts:
import { FastifyInstance, FastifyPluginCallback } from 'fastify'; type FastifyInstanceA = FastifyInstance & { utilA: string; }; export const pluginA: FastifyPluginCallback<{}, {}, FastifyInstanceA> = (instance, opts, done) => { instance.decorate('utilA', 'AAA'); // ... 插件逻辑 done(); };
plugin-b.ts同理,这样主文件导入两个插件时,各自的类型不会互相干扰。
内容的提问来源于stack exchange,提问作者b4v
相关产品推荐
相关产品推荐

