想象一个 TypeScript (4.2.2) 函数接收一个string
or a Promise<string>
并使用最初收到的相同类型返回答案,例如:
function trim(textOrPromise) {
if (textOrPromise.then) {
return textOrPromise.then(value => result.trim());
}
return textOrPromise.trim();
}
我想使用泛型定义此类函数的签名来指示传入Promise
总是会导致Promise
,并传入一个string
结果是string
为此,我定义了以下重载:
function trim(text: Promise<string>): Promise<string>
function trim(text: string): string
function trim(text: any): any {
if (text.then) {
return text.then(result => result.trim()); // returns Promise<string>
}
return text.trim(); // returns string
}
只要参数明确定义为,就可以正确转换string
or a Promise<string>
:
let value: string
trim(value) // fine
let value: Promise<string>
trim(value) // fine
但是,当我使用 a 定义参数时联合型 https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html (Promise<string> | string
):
let value: Promise<string> | string
trim(value) // error: TS2769
我收到以下转换错误:
TS2769: No overload matches this call.
Overload 1 of 2, '(text: Promise<string>): Promise<string>', gave the following error.
Argument of type 'string | Promise<string>' is not assignable to parameter of type 'Promise<string>'.
Type 'string' is not assignable to type 'Promise<string>'.
Overload 2 of 2, '(text: string): string', gave the following error.
Argument of type 'string | Promise<string>' is not assignable to parameter of type 'string'.
Type 'Promise<string>' is not assignable to type 'string'.
有趣的是,当我将联合类型添加到函数签名时,该示例会正确转换并表现正常
function trim(text: Promise<string>): Promise<string>
function trim(text: string): string
function trim(text: Promise<string> | string): Promise<string> | string
function trim(text: any): any {
if (text.then) {
return text.then(result => result.trim());
}
return text.trim();
}
let value: Promise<string> | string
trim(value) // fine
通过最后一个实现,TypeScript 知道当函数接收到Promise
它将返回一个Promise
,当它收到一个string
它返回一个string
。与联盟相反Promise<string> | string
正如第三次过载所暗示的那样。
如果有人能够解释这种行为以及必须为联合类型添加重载的原因,我将不胜感激。