TypeScript中如何实现符合接口T的MultiProxy<T>多实例代理类
TypeScript MultiProxy 多实例代理实现方案
核心实现逻辑
我们可以通过组合TS类型约束+内置Proxy代理来实现需求,内置Proxy本身支持自定义拦截逻辑,只需在拦截器中添加多实例遍历调用的逻辑即可:
// 泛型约束T为对象类型,适配interface场景 type MultiProxy<T extends object> = T; function createMultiProxy<T extends object>(targets: T[]): MultiProxy<T> { return new Proxy({}, { // 拦截属性访问 get(_, prop: keyof T) { const allValues = targets.map(t => t[prop]); // 访问属性为方法时,返回多实例调用包装函数 if (typeof allValues[0] === 'function') { return (...args: unknown[]) => { // 所有子实例执行同名方法,传入相同参数 return allValues.map(fn => (fn as Function).apply(this, args)); }; } // 非方法属性默认返回所有实例的属性值数组,可按需修改返回策略 return allValues; }, // 可选:拦截属性赋值,同步更新所有子实例的对应属性 set(_, prop: keyof T, value: unknown) { targets.forEach(t => t[prop] = value); return true; } }) as MultiProxy<T>; }
使用示例
// 定义业务接口 interface ILogger { log: (msg: string) => void; error: (msg: string) => void; level: string; } // 实现多个接口实例 class ConsoleLogger implements ILogger { level = 'info'; log(msg: string) { console.log(`[控制台] ${msg}`); } error(msg: string) { console.error(`[控制台] ${msg}`); } } class FileLogger implements ILogger { level = 'warn'; log(msg: string) { // 模拟写文件逻辑 console.log(`[文件日志] ${msg}`); } error(msg: string) { console.error(`[文件日志] ${msg}`); } } // 创建多代理实例,类型完全和ILogger对齐 const logger = createMultiProxy<ILogger>([new ConsoleLogger(), new FileLogger()]); // 调用代理方法,自动触发所有子实例的同名方法 logger.log('测试日志'); // 输出: // [控制台] 测试日志 // [文件日志] 测试日志 // 非方法属性默认返回所有实例的属性值数组 console.log(logger.level); // 输出:['info', 'warn'] // 赋值属性会同步更新所有子实例 logger.level = 'error'; console.log(logger.level); // 输出:['error', 'error']
可选调整项
- 方法返回值策略:默认返回所有子实例的调用结果数组,可根据需求修改为返回第一个结果、最后一个结果,或者忽略返回值返回void
- 异步方法支持:如果子实例的方法是异步函数,可将包装函数改为async,用
Promise.all等待所有调用完成 - 异常处理:可添加try/catch逻辑,控制单个子实例调用失败时是否中断其他实例的执行
内容的提问来源于stack exchange,提问作者Uri Abramson
相关产品推荐
相关产品推荐

