问题
fetchMock.mock
被键入以接受0-3个参数:
mock(matcher: MockMatcher | MockOptions, response: MockResponse | MockResponseFunction, options?: MockOptions): this;
mock(options: MockOptions): this;
mock(): this;
wheresrhys/fetch-mock/types/index.d.ts:L270-L294
试图将
any
融入其中。
任何
不会阻止TypeScript检查排列的潜在长度,它只会不检查元组中的项的类型是否可用于函数参数。例如:
function fn(a: number, b: number) {}
const foo: any[] = [];
const bar: [any, any] = ["one", "two"];
fn(...foo); // Not OK â
// ~~~~~~
// A spread argument must either have a tuple type or be passed to a rest parameter.
fn(...bar); // OK, even though we're passing in strings â
TypeScript Playground
解决方案
错误消息告诉您解决方案(重点是我的):
散布论点必须
具有元组类型
或者是
传递给rest参数
。
让我们来探讨一下这两个问题。
传递给rest参数
如果函数被类型化为接受rest参数,它就会工作,因为rest参数本质上是可选参数的无限列表。但是,在您的情况下,您无法控制库的接口。因此,您将不得不使用另一个选项。
将参数键入为元组
元组是一个具有两个显著特性的列表。它们是:
-
有限的
。这保证了长度将与您尝试使用的函数的参数长度相匹配。
-
已订购
。这保证了每个索引处的值的类型将与同一索引处的函数参数相匹配。
使用
Parameters
?
tl;dr这不起作用,请参阅链接的GitHub问题
TypeScript提供了一个名为
Parameters
它从传递给它的函数的参数中使用的类型构造元组类型,所以理论上你可以这样做:
function mockRequest(...args: Parameters<typeof fetchMock.mock>) {
return fetchMock.mock(...args);
}
TypeScript Playground
然而,在撰写本文时,
参数
仅返回上次重载的参数(请参阅
TypeScript issue 14107
和
TypeScript issue 32164
)。在上述例子中,
mockRequest
将被键入为不接受任何参数,因为
fetchMock.mock
没有参数。
手动类型
使用它会很可爱
参数
。看起来我们将不得不手动添加类型。下面是一个工作示例:
type Overload1 = [matcherOrOptions: MockMatcher | MockOptions, response: MockResponse | MockResponseFunction, options?: MockOptions];
type Overload2 = [matcherOrOptions: MockOptions];
type Overload3 = [];
type Args = Overload1 | Overload2 | Overload3;
function mockRequest(...args: Args) {
return args.length === 1 ?
fetchMock.mock(...args) :
args.length >= 2 ?
fetchMock.mock(...args as Overload1) :
fetchMock.mock();
}
TypeScript Playground
由于无法确定的原因,TypeScript无法缩小
args
到
Overload1
符合条件
args.length >= 2
因此铸造是必要的。