为什么 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
}
关于javascript - Typescript 中的 XHR 拦截器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70879794/