javascript - Typescript 中的 XHR 拦截器

标签 javascript typescript xmlhttprequest

为什么 Typescript 中不允许使用以下猴子补丁?

const oldXHROpen = window.XMLHttpRequest.prototype.open

window.XMLHttpRequest.prototype.open = function (
    method: string,
    url: string
): void {
    return oldXHROpen.apply(this, [method, url])
}

它给出以下错误:

Argument of type '[string, string]' is not assignable to parameter of type '[method: string, url: string | URL, async: boolean, username?: string | null | undefined, password?: string | null | undefined]'.
  Source has 2 element(s) but target requires 3.

但是,当查看 open 的定义时,有一个只需要两个参数的方法。

open(method: string, url: string | URL): void;

最佳答案

这是 TypeScript 的设计限制;请参阅microsoft/TypeScript#38353了解更多信息。

TypeScript standard library's typings对于 the XHMLHttpRequest.open() method看起来像这样:

interface XMLHttpRequest {
    open(method: string, url: string | URL): void;
    open(method: string, url: string | URL, async: 
      boolean, username?: string | null, password?: string | null): void;
}

有两个调用签名,这使得 open() 成为 overloaded TypeScript 中的方法。如果您直接调用重载方法或函数,编译器将根据您传入的参数选择其中一个重载。

但它无法纯粹在类型级别上做到这一点。如果您开始以编程方式操作重载函数类型的类型,编译器将立即选择一个调用签名,而无需尝试找出哪一个最适合该情况。通常这是最后一个调用签名。

在本例中,假设您有 the --strictBindCallApply compiler option已启用,the apply() method for CallableFunction只能看到 XHMLHttpRequest.open() 的第二个调用签名。该调用签名至少需要三个参数,因此当您 apply() 其中两个参数时,编译器会生气。哎呀。


这种情况下的解决方法是您手动将 oldXHROpen 的类型从一对调用签名扩大到您尝试支持的单个调用签名。由于加宽是一种安全的操作,因此您可以使用 type annotation 来完成此操作。并且不放弃任何类型安全:

const oldXHROpen: (method: string, url: string | URL) => void =
  window.XMLHttpRequest.prototype.open // okay

完成此操作后,apply() 方法只会看到您关心的 open() 调用签名,并且一切正常:

window.XMLHttpRequest.prototype.open = function (
  method: string,
  url: string
): void {
  return oldXHROpen.apply(this, [method, url])  // okay
}

Playground link to code

关于javascript - Typescript 中的 XHR 拦截器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70879794/

相关文章:

javascript - React Native,NavigatorIOS,undefined 不是一个对象(评估 'this.props.navigator.push')

javascript - Spotify API,无法链接两个 API 调用(Authorization-GetSong)

python - 需要帮助来模拟 xhr 请求

javascript - 如何将两个字符串值作为整数进行比较?

javascript - X 轴的固定比例,从不改变 amcharts

javascript - 在转译流程/ typescript 后保留类型检查

typescript - 在 Typescript 中,什么是 !取消引用成员时的(感叹号/爆炸)运算符?

javascript - 对期望为 'number | string | undefined' 的属性使用泛型类型值

javascript - Tabris.js XMLHttpRequests 不接受响应 : readystate 1

javascript - 使用 Bluebird promise