首页 > 解决方案 > 传播参数不一致的 TypeScript 错误

问题描述

对于此功能:

function foo(a: number, b: number) {/* ... */}

片段 1 导致错误:

foo(1, ...[]);

预期 2 个参数,但得到 1 个或更多。

片段 2 导致错误:

foo(1, 2, ...[]);

预期 2 个参数,但得到 3 个或更多。

看起来很奇怪的是,在第二种情况下它不是“得到 2 个或更多”。该代码不会尝试解决任何特定问题,只是想知道到底发生了什么。

为什么 TypeScript 对这些片段 1 和 2 的处理方式不同?


对于因相同错误而发现此问题的用户,解决此问题的一种方法是更严格地键入展开的参数:

foo(1, ...[2] as const);
foo(1, ...[2] as [number]);
foo(1, 2, ...[] as const);
foo(1, 2, ...[] as []);

标签: typescriptargumentsspread-syntax

解决方案


这是一个没有任何“不应该是元组”方面的最小示例

declare const arr: number[];
function foo(a: number, b: number) {/* ... */ }

foo(...arr); // expected 2, got 0 or more
foo(1, ...arr); // expected 2, got 1 or more
foo(1, 2, ...arr) // expected 2, got *3* or more ?!
foo(1, 2, 3, ...arr) // expected 2, got *4* or more ?!

这些都是错误;在前两种情况下,编译器必须出错,因为可能没有使用足够的参数调用函数。

在最后两种情况下,人们可能会争辩说应该没有错误,因为调用具有比它需要的更多参数的函数通常是安全的(请参阅TypeScript 常见问题解答,了解将这一原则应用于函数类型的可分配性),但编译器会生成一个无论如何这里都会出错。

但是,您不是在问“为什么会出现错误”。你问“为什么会出现这个错误”?毕竟,问题在于foo(1, 2, ...arr)传递 2 个或更多参数,而编译器正在强制执行2。那么为什么编译器会说你传递的是“ 3 or more”而不是“ 2 or more”?

根据microsoft/TypeScript#20071的说法,这似乎是一个有意的决定,该请求为过度传播参数引入了错误:

此 PR 还将过度传播参数的错误更改为更易于理解:

“预期 3 个参数,但至少得到 4 个”。

以前的错误应该是“预期 3 个参数,但至少得到 3 个”,这在技术上也是正确的,但无法理解。

我想看到“预期为 2,但至少得到 2”的用户会感到困惑,因为“至少 2”似乎与“2”兼容。相反,他们决定写出一条消息,即使不是准确的,也肯定是错误条件。这是官方的回答。

您可以在这些行中看到,给定一个参数列表,例如(a1, a2, a3, ...spreadArg)spread 参数,如果您有足够的参数而没有它,那么它就会被计算在内;否则不是。因此,如果它需要 2 个参数,则(1, ...arr)算作 1 个参数,但(1, 2, ...arr)算作 3 个。


坦率地说,在研究了这个之后我不太高兴,因为我可以想象错误消息是正确的,但不太清楚(在我看来):

foo(...arr); // expected exactly 2 arguments, but maybe got too few or too many
foo(1, ...arr); // expected exactly 2 arguments, but maybe got too few or too many 
foo(1, 2, ...arr); // expected exactly 2 arguments, but maybe got too many
foo(1, 2, 3, ...arr); // expected exactly 2 arguments, but got too many

这已经在microsoft/TypeScript#20097(关闭为“按预期工作”)和microsoft/TypeScript#20372(打开为“需要帮助”)中报告过,所以如果你非常关心它,你(或任何人)阅读这个)可以给其中一个,甚至提交一个修复它的请求请求。


好的,希望有帮助;祝你好运!

游乐场链接fwiw


推荐阅读