TypeScript API服务:如何统一校验方法调用时的存在性?
嘿,这个需求完全可行,而且确实能帮你省去大量重复的校验代码!我之前做TypeScript API服务时也遇到过类似场景,用Proxy代理就能完美解决这个问题——不需要在每个方法里写重复逻辑,只需要在基类的构造函数里做一次统一拦截就行。
核心思路
利用ES6的Proxy来拦截类实例的方法访问,当调用get开头的方法时,自动触发统一的校验逻辑,校验通过后再执行原方法。这样所有子类的get类方法都能共享这套校验逻辑,不用重复编写。
具体实现步骤
1. 编写基础API基类
先定义一个BaseApi基类,在它的构造函数里返回一个Proxy实例,负责拦截所有属性访问:
class BaseApi<T extends object> { constructor(target: T) { return new Proxy(target, { // 拦截属性获取(包括方法) get(targetInstance, methodName: string) { // 只针对get开头的方法做统一处理 if (methodName.startsWith('get')) { const originalMethod = (targetInstance as any)[methodName]; // 返回一个包装后的函数,先执行校验再调用原方法 return function(...args: any[]) { // 校验1:检查该方法是否存在 if (typeof originalMethod !== 'function') { throw new Error(`API方法 ${methodName} 不存在,请检查方法名是否正确`); } // 这里可以添加更多统一校验逻辑,比如参数合法性检查 if (args.length === 0) { throw new Error(`调用 ${methodName} 时需要传入至少一个参数`); } // 校验通过,执行原方法并返回结果 return originalMethod.apply(targetInstance, args); }; } // 非get开头的方法/属性,直接返回原内容 return (targetInstance as any)[methodName]; } }) as T; } }
2. 子类继承基类实现业务方法
你的具体API服务类只需要继承BaseApi,专注实现业务逻辑即可,不用管校验:
class UserApi extends BaseApi<UserApi> { constructor() { // 把当前实例传给基类的Proxy super(this); } // 业务方法:获取用户信息 getUser(userId: number) { return { id: userId, name: '张三', email: 'zhangsan@example.com' }; } // 业务方法:获取用户权限 getUserPermissions(userId: number) { return ['view', 'edit']; } // 非get开头的方法,不会触发统一校验 updateUser(userId: number, userData: { name: string }) { return { success: true, message: '用户信息更新成功' }; } }
3. 测试效果
现在调用API方法时,会自动触发统一校验:
const userApi = new UserApi(); // 正常调用:校验通过,返回结果 console.log(userApi.getUser(123)); // 输出:{ id: 123, name: '张三', email: 'zhangsan@example.com' } // 调用不存在的get方法:触发校验报错 userApi.getNonExistentMethod(); // 抛出错误:API方法 getNonExistentMethod 不存在,请检查方法名是否正确 // 调用get方法但不传参数:触发参数校验报错 userApi.getUser(); // 抛出错误:调用 getUser 时需要传入至少一个参数
补充:TypeScript类型支持
上面的基类用了泛型<T extends object>,确保子类的方法类型能被TypeScript正确识别,不会因为Proxy而丢失类型提示——你在IDE里调用userApi.getUser()时,依然能看到参数和返回值的类型提示。
为什么不用其他方案?
- 装饰器:虽然也能实现,但需要给每个
get方法手动加装饰器,还是有重复操作,不符合你“避免重复”的需求。 - 手动在构造函数绑定:逐个监听方法调用的话,代码繁琐且扩展性差,新增
get方法时还要手动更新绑定逻辑。
而Proxy的方案是一次性统一拦截,后续新增get方法时完全不需要修改基类代码,自动享受统一校验。
内容的提问来源于stack exchange,提问作者user8116198
相关产品推荐
相关产品推荐

