【问题标题】:Writing wrapper to third party class methods in TS将包装器写入 TS 中的第三方类方法
【发布时间】:2023-01-07 21:35:01
【问题描述】:

我正在尝试为所有第三方 API 接口和 SDK 编写一个包装器,以标准化但可自定义的方式记录请求。我想这样做的方法是将第三方 API(通常通过 new API() 调用实例化)传递到包装类 (APIClient)。该客户端接收到一个对象,该对象具有映射到日志记录功能的第三方 API 上的某些方法(例如,我可以说我可以指定何时需要清理 PII)。它迭代此对象并自行重新定义this第三方API 上定义的方法,在调用第三方方法后调用日志记录函数。通过这种方式,API 可以具有与第三方 API 相同的接口,并具有自定义行为的优势。

当然,我已经为这方面的打字苦苦挣扎了很长时间,感觉我可能快要让它工作了,但我还不能完全完成。我被 TS 文档中关于“Mixins”的部分所启发,但我不确定这是要走的路。

我得到了一些非常令人困惑的错误:

Type 'Function' provides no match for the signature '(...args: any): any'.

No index signature with a parameter of type 'string' was found on type 'ApiClient<T>'.

(第二个不那么令人困惑,我知道 Object.entries 将键值对作为字符串和值提供,但我不知道还能做什么)

有没有人看到这里可能出了什么问题,我该如何解决?谢谢你。

type Constructor = new (...args: any[]) => {};
type Method<T, K extends keyof T> = T[K] extends Function ? T[K] : never;

class ApiClient<T extends Constructor> {
  _api: T;

  constructor(api: T, logConfig: Record<keyof T, () => void>) {
    this._api = api;

    for (const [method, fn] of Object.entries(logConfig)) {
      this[method] = this.createWrappedMethod(method, fn)
     }
  }

  createWrappedMethod<
    N extends keyof InstanceType<T>,
    M extends Method<InstanceType<T>, N>,
  >(name: N, logFn: () => void) {
    return async (...args: Parameters<M>) => {
      try {
        const res = await this._api[name](...args);
        // do logging
      } catch {
        // handle error`
      }
    };
  }
}

【问题讨论】:

    标签: javascript typescript class typescript-generics


    【解决方案1】:

    我不确定如何用您当前的方法解决打字问题,但是,看起来您正在做的事情与 Proxy 对象的设计目的非常相似。

    简而言之,Proxy 对象允许您重新定义对象上的某些操作,例如属性访问,从而允许您包装和覆盖函数以插入日志记录和卫生。

    例如,这是一个包裹在 Proxy 中的对象,它只是将方法调用的结果打印到控制台:

    const api = new API();
    
    const proxy = new Proxy(api, {
        get(target, prop) {
            if (typeof target[prop] !== "function") {
                return target[prop];
            }
            return async (...args) => {
                const res = await target[prop](...args);
                console.log(res)
                // do more stuff...
                return res;
            };
        },
    });
    

    这也自动适用于 TypeScript;编译器会将 Proxy 对象键入并识别为原始对象的类型。换句话说,在 TypeScript 中,Proxy(new API(), {...}) 仍然是 API

    【讨论】:

    • 我没想过使用代理,谢谢
    猜你喜欢
    • 2011-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-17
    • 1970-01-01
    相关资源
    最近更新 更多