传播参数不一致的 TypeScript 错误

Posted

技术标签:

【中文标题】传播参数不一致的 TypeScript 错误【英文标题】:Inconsistent TypeScript error for spread arguments 【发布时间】:2020-10-04 23:33:53 【问题描述】:

对于这个函数:

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

片段 1 导致错误:

foo(1, ...[]);

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

片段 2 导致错误:

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

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

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

为什么 TypeScript 对这些 sn-ps 1 和 2 的处理方式不同?


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

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

【问题讨论】:

要清楚,您的问题是“为什么说 3 而不是 2?”而不是“为什么扩展数组文字扩展到数组而不是作为元组类型维护?”对吗? 非常感谢您的详细回答。我会继续关注你提到的问题。是的,元组确实不是问题。 【参考方案1】:

这是一个minimal example,它没有任何“不应该这是一个元组”方面的内容:

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 ?!

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

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

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

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

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

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

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

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

你可以在these lines 中看到,给定一个像(a1, a2, a3, ...spreadArg) 这样的参数列表,如果你有足够的参数没有它,则计算扩展参数;否则不是。因此,如果它需要 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(打开为“需要帮助”)中报告过,所以如果你非常关心它,你(或任何阅读这)可以给其中一个 ? 甚至提交修复它的拉取请求。


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

Playground link fwiw

【讨论】:

以上是关于传播参数不一致的 TypeScript 错误的主要内容,如果未能解决你的问题,请参考以下文章

是否可以在 TypeScript 中传播独特的泛型类型?

Typescript 编译的 Javascript 代码不起作用(variable.default.function())

传播运算符的打字稿抛出错误

Spring事务传播

TypeScript: type alias 与 interface

TypeScript 函数