Typescript 无法识别预期的重载函数签名
Typescript does not recognize an expected overloaded function signature
我正在努力解决 typescript 重载问题。
我正在使用带有 typescript 的 googleapis 库并尝试获取所有 tagmanager 帐户记录。
如果响应主体包含 nextPageToken,则 googleapis 列表函数需要分页,因此我想创建对所有内容进行分页并获取所有记录的函数。
我的想法是创建一个这样的 curry 函数。它以列表函数为参数,并使用 nextPageToken 不断调用列表函数,直到 nextPageToken 不包含在列表函数的返回数据中。
// ex. 1)
const allAccounts = await paginateAll(tagmanager.accounts.list)({
// specify tagmanager.accounts.list parameter
});
// ex. 2)
const allContainers = await paginateAll(tagmanager.accounts.containers.list)({
// specify tagmanager.accounts.containers.list parameter
});
我创建了一个如下所示的 paginateAll
签名,但似乎 typescript 没有解析正确的重载。
export const paginateAll = <P1, P2, R>(
list: (params?: P1, options?: P2) => Promise<R>,
): ((arg1: P1, arg2: P2) => Promise<Array<R>>) => async (a, b) => {
// some procedure...
};
const fetchAllAccounts = paginateAll(tagmanager.accounts.list)
^^^
=== ERROR ===
Argument of type '{ (params: Params$Resource$Accounts$List, options: StreamMethodOptions): GaxiosPromise<Readable>; (params?: Params$Resource$Accounts$List | undefined, options?: MethodOptions | undefined): GaxiosPromise<...>; (params: Params$Resource$Accounts$List, options: StreamMethodOptions | BodyResponseCallback<...>, callback: ...' is not assignable to parameter of type '(params?: BodyResponseCallback<Schema$ListAccountsResponse> | undefined, options?: unknown) => Promise<unknown>'.
Types of parameters 'params' and 'params' are incompatible.
Type 'BodyResponseCallback<Schema$ListAccountsResponse> | undefined' is not assignable to type 'Params$Resource$Accounts$List'.
Type 'undefined' is not assignable to type 'Params$Resource$Accounts$List'.
googleapis list
函数有 6 个重载,如下所示。我希望 paginateAll
选择第二个签名。
1. list(params: Params$Resource$Accounts$List, options: StreamMethodOptions): GaxiosPromise<Readable>;
2. list(params?: Params$Resource$Accounts$List, options?: MethodOptions): GaxiosPromise<Schema$ListAccountsResponse>;
3. list(params: Params$Resource$Accounts$List, options: StreamMethodOptions | BodyResponseCallback<Readable>, callback: BodyResponseCallback<Readable>): void;
4. list(params: Params$Resource$Accounts$List, options: MethodOptions | BodyResponseCallback<Schema$ListAccountsResponse>, callback: BodyResponseCallback<Schema$ListAccountsResponse>): void;
5. list(params: Params$Resource$Accounts$List, callback: BodyResponseCallback<Schema$ListAccountsResponse>): void;
6. list(callback: BodyResponseCallback<Schema$ListAccountsResponse>): void;
如果你们能告诉我为什么会这样,我将不胜感激...
==== 更新 ====
我用 TypeScript Playground 重现了我的问题中的错误。 (为了简单起见,我没有加咖喱)
type Params = {
value1: string;
value2: string;
}
type Options1 = {
option1Value: string;
};
type Options2 = {
option2Value: string;
};
type Resonse1 = {
response1Value: string;
}
type Response2 = {
response2Value: string;
}
type Callback<T> = () => T
declare function func(params: Params, options: Options1): Promise<Resonse1>;
declare function func(params?: Params, options?: Options2): Promise<Response2>;
declare function func(params: Params, options: Options1 | Callback<Resonse1>, callback: Callback<Resonse1>): void;
declare function func(params: Params, options: Options2 | Callback<Response2>, callback: Callback<Response2>): void;
declare function func(params: Params, callback: Callback<Response2>): void;
declare function func(callback: Callback<Response2>): void;
const anotherFunc = async <P1, P2, R>(
fn: (params?: P1, options?: P2) => Promise<R>,
): Promise<R> => {
return fn();
}
const test = anotherFunc(func);
编译器无法 select 重载,除非您实际直接使用输入调用重载函数。如果将重载函数传递给另一个函数并尝试使用泛型类型推断,编译器将不会按照您想要的方式执行重载解析。它只是选择一个过载,通常是第一个或最后一个。这是 TypeScript 的设计限制,请参阅 microsoft/TypeScript#30369 了解更多信息。
此处的解决方法是让您选择您要使用的签名。这是一种方法:
const f: (params?: Params, options?: Options2) => Promise<Response2> = func;
const test = anotherFunc(f);
在这里,我们将 func
分配给一个变量 f
,其类型对应于一个函数,该函数仅具有我们想要推断的调用签名。允许此分配。由于 f
没有超载,因此调用 anotherFunc(f)
可以正常工作。
我正在努力解决 typescript 重载问题。
我正在使用带有 typescript 的 googleapis 库并尝试获取所有 tagmanager 帐户记录。 如果响应主体包含 nextPageToken,则 googleapis 列表函数需要分页,因此我想创建对所有内容进行分页并获取所有记录的函数。
我的想法是创建一个这样的 curry 函数。它以列表函数为参数,并使用 nextPageToken 不断调用列表函数,直到 nextPageToken 不包含在列表函数的返回数据中。
// ex. 1)
const allAccounts = await paginateAll(tagmanager.accounts.list)({
// specify tagmanager.accounts.list parameter
});
// ex. 2)
const allContainers = await paginateAll(tagmanager.accounts.containers.list)({
// specify tagmanager.accounts.containers.list parameter
});
我创建了一个如下所示的 paginateAll
签名,但似乎 typescript 没有解析正确的重载。
export const paginateAll = <P1, P2, R>(
list: (params?: P1, options?: P2) => Promise<R>,
): ((arg1: P1, arg2: P2) => Promise<Array<R>>) => async (a, b) => {
// some procedure...
};
const fetchAllAccounts = paginateAll(tagmanager.accounts.list)
^^^
=== ERROR ===
Argument of type '{ (params: Params$Resource$Accounts$List, options: StreamMethodOptions): GaxiosPromise<Readable>; (params?: Params$Resource$Accounts$List | undefined, options?: MethodOptions | undefined): GaxiosPromise<...>; (params: Params$Resource$Accounts$List, options: StreamMethodOptions | BodyResponseCallback<...>, callback: ...' is not assignable to parameter of type '(params?: BodyResponseCallback<Schema$ListAccountsResponse> | undefined, options?: unknown) => Promise<unknown>'.
Types of parameters 'params' and 'params' are incompatible.
Type 'BodyResponseCallback<Schema$ListAccountsResponse> | undefined' is not assignable to type 'Params$Resource$Accounts$List'.
Type 'undefined' is not assignable to type 'Params$Resource$Accounts$List'.
googleapis list
函数有 6 个重载,如下所示。我希望 paginateAll
选择第二个签名。
1. list(params: Params$Resource$Accounts$List, options: StreamMethodOptions): GaxiosPromise<Readable>;
2. list(params?: Params$Resource$Accounts$List, options?: MethodOptions): GaxiosPromise<Schema$ListAccountsResponse>;
3. list(params: Params$Resource$Accounts$List, options: StreamMethodOptions | BodyResponseCallback<Readable>, callback: BodyResponseCallback<Readable>): void;
4. list(params: Params$Resource$Accounts$List, options: MethodOptions | BodyResponseCallback<Schema$ListAccountsResponse>, callback: BodyResponseCallback<Schema$ListAccountsResponse>): void;
5. list(params: Params$Resource$Accounts$List, callback: BodyResponseCallback<Schema$ListAccountsResponse>): void;
6. list(callback: BodyResponseCallback<Schema$ListAccountsResponse>): void;
如果你们能告诉我为什么会这样,我将不胜感激...
==== 更新 ====
我用 TypeScript Playground 重现了我的问题中的错误。 (为了简单起见,我没有加咖喱)
type Params = {
value1: string;
value2: string;
}
type Options1 = {
option1Value: string;
};
type Options2 = {
option2Value: string;
};
type Resonse1 = {
response1Value: string;
}
type Response2 = {
response2Value: string;
}
type Callback<T> = () => T
declare function func(params: Params, options: Options1): Promise<Resonse1>;
declare function func(params?: Params, options?: Options2): Promise<Response2>;
declare function func(params: Params, options: Options1 | Callback<Resonse1>, callback: Callback<Resonse1>): void;
declare function func(params: Params, options: Options2 | Callback<Response2>, callback: Callback<Response2>): void;
declare function func(params: Params, callback: Callback<Response2>): void;
declare function func(callback: Callback<Response2>): void;
const anotherFunc = async <P1, P2, R>(
fn: (params?: P1, options?: P2) => Promise<R>,
): Promise<R> => {
return fn();
}
const test = anotherFunc(func);
编译器无法 select 重载,除非您实际直接使用输入调用重载函数。如果将重载函数传递给另一个函数并尝试使用泛型类型推断,编译器将不会按照您想要的方式执行重载解析。它只是选择一个过载,通常是第一个或最后一个。这是 TypeScript 的设计限制,请参阅 microsoft/TypeScript#30369 了解更多信息。
此处的解决方法是让您选择您要使用的签名。这是一种方法:
const f: (params?: Params, options?: Options2) => Promise<Response2> = func;
const test = anotherFunc(f);
在这里,我们将 func
分配给一个变量 f
,其类型对应于一个函数,该函数仅具有我们想要推断的调用签名。允许此分配。由于 f
没有超载,因此调用 anotherFunc(f)
可以正常工作。