我有一个重载函数f
,有两个可能的参数:
const f: {
(x: number): void;
(x: string): void;
} = (x: number | string) => {};
......以及应该传递给函数f
的值的数组arr
const arr = [1, "1"];
...当类型正确时,打印脚本日志:
f(1); // works
f("1"); // works
f(arr[0]); // error: No overload matches this call.
为什么它显示这个错误,即使函数f
可以接受number | string
可能值中的number
和string
?
1条答案
按热度按时间rslzwgfq1#
您遇到了TypeScript长期缺失的功能;请参阅microsoft/TypeScript#14107中的相关特性请求。当您调用重载函数时,编译器当前只能将调用解析为该函数的一个调用签名。它不会尝试合并调用签名或将调用解析为多个签名。因此,即使 * 概念上 *使用联合类型
X | Y
的参数调用{(x: X): A; (y: Y): B;}
应该是可接受的,并且返回A | B
类型的值,编译器不执行此类分析。根据TypeScript程序管理器的评论,目前还没有这样做,因为你不能只对所有重载函数这样做,例如,允许像
{(xy: X | Y, tu: T| U): A | B}
一样调用{(x: X, t: T): A; (y: Y, u: U): B}
是一个错误,因为你不应该被允许为第一个参数传入X
,为第二个参数传入U
。我们必须检测到只有一个参数类型不同的多个调用签名的情况,并将它们组合起来,但根据评论,这可能不优雅,可能代价高昂,而且可能有奇怪的边缘情况。这就是问题的答案如果你想看到这种情况发生,你可能想👍在GitHub中给特性请求一个,但是它不太可能改变太多。
您并没有问应该怎么做,但是在实现之前,建议的解决方案是添加另一个重载调用签名,它接受您想要的内容:
尽管在上面的例子中,由于前两个调用签名都返回
void
,所以没有理由再使用它们。如果它们返回不同的类型,那么您可能仍然需要三个调用签名。如果你的底层用例不允许你重新定义函数类型,那么你必须用某种方法来解决它,比如Assert
f
接受你传递的参数:Playground代码链接