在普通的JavaScript中重新分配函数是非常好的代码……

function f() {}

f = function() {}

...,但当我对TypeScrip执行此操作时,我得到一个编译器错误,告诉我这是不允许的?!(playground link)

function f() {}

f = function () {}; /*
~ Cannot assign to 'f' because it is a function. */

所以我想知道这个功能似乎被禁止的特殊原因是什么.我知道这适用于function expressions(参见this playground),但不适用于函数声明.我在TypeScript documentation公路上找不到任何有用的东西,也找不到其他任何地方.

请注意,我对解决方法不感兴趣,而是对此行为的实际解释感兴趣.

推荐答案

警告:我不知道这是否构成了对"为什么类型脚本不允许重新分配通过Function语句声明的函数?"的客观正确答案.可以肯定的是,我必须找到一些权威的文件或官方声明来提供这一特定禁令背后的理由,但到目前为止我还没有找到.因此,考虑到关于其他情况的这样的说法,以下只是一个有根据的猜测.


允许所有有效的JavaScript在类型脚本中编译而不发出编译器错误,这不是设计目标之一(尽管它is是设计目标之一,即使有这样的错误,代码也将被编译,emitted将被编译为Java脚本).发出编译器错误的试金石测试不是"这是否会在JavaScript中导致运行时错误",而是"这是否可能是一个编码错误".有关权威来源,请参阅What does "all legal JavaScript is legal TypeScript" mean?及其答案.

有关这方面的示例,请参阅:

在所有这些情况下,JavaScript都允许一些东西,并且有一个定义良好的结果,但TypeScrip认为这样做是错误的.

因此,"在普通的JavaScript中重新分配函数是非常好的代码"可能是真的,但这并不一定意味着它应该是完全好的TypeScript代码.

请注意,我并不是说我个人同意上述所有情况或这一情况的决定.我肯定有很多次不同意TS团队关于允许或禁止某些编码技术的决定,通常这归结为支持某些用例的优先级的不同.如果我认为某些用例比TS团队更重要,那么当该语言没有负担能力时,我可能会不高兴.相反,如果我认为语言中有一个重大的安全漏洞,但TS团队关心该漏洞启用的一些用例,那么当语言不健全时,我可能会不高兴.这些最终归结为真实世界的代码统计、编译器性能和TS语言维护者的主观意见的组合.


声明了function条语句的函数不能在类型脚本中重新分配的可能原因是,TS团队认为这样做可能是错误的.

MDN's documentation for function statements currently表示"函数声明可以重新赋值,但应避免这样做".我不知道我们是否可以认为MDN在这里是权威的,但至少有一个数据点.

一般来说,如果像这样的事情发生,那将是不幸的

parseFloat = x => 0

是不是没有错误,对吗?除非TypeScrip引入了readonly函数声明的概念,并将每个本地JS函数标记为一个,否则我们主要只剩下两个极端:"允许所有函数重新分配(其类型匹配)"或"禁止所有函数重新分配",而TS Select 了后者.

当我查看对于GitHub来说太大的UIchecker.ts file时,大约在第28,031行,我看到

if (assignmentKind) {
  if (!(localOrExportSymbol.flags & SymbolFlags.Variable) &&
    !(isInJSFile(node) && localOrExportSymbol.flags & SymbolFlags.ValueModule)) {
    const assignmentError = localOrExportSymbol.flags & SymbolFlags.Enum ? Diagnostics.Cannot_assign_to_0_because_it_is_an_enum
      : localOrExportSymbol.flags & SymbolFlags.Class ? Diagnostics.Cannot_assign_to_0_because_it_is_a_class
      : localOrExportSymbol.flags & SymbolFlags.Module ? Diagnostics.Cannot_assign_to_0_because_it_is_a_namespace
      : localOrExportSymbol.flags & SymbolFlags.Function ? Diagnostics.Cannot_assign_to_0_because_it_is_a_function
      : localOrExportSymbol.flags & SymbolFlags.Alias ? Diagnostics.Cannot_assign_to_0_because_it_is_an_import
      : Diagnostics.Cannot_assign_to_0_because_it_is_not_a_variable;

因此,TypeScrip的立场是,重新分配给function语句与重新分配class语句或module语句是同一类错误.也就是说,这就像是一个类别错误.你不是要打击这些东西.


这就对了.我所知道的事实是,它在TypeScrip中是不允许的,而在其他不允许有效的JavaScript的情况下,这是因为TS团队认为这样的代码可能是错误的.这里可能也是如此,而且有间接证据表明这一点.

Typescript相关问答推荐

如何使用另一个类型的属性中的类型

调用另一个函数的函数的Typescript类型,参数相同

net::BER_RECTION_REUSED和Uncatch使用Axios和TanStack-Query useMutation时未捕获错误(DelivercMutation)

无法将select选项的值设置为ngFor循环中的第一个元素

如何为父类构造函数中的修饰属性赋值?

如何通过TypeScript中的工厂函数将区分的联合映射到具体的类型(如类)?

类型脚本返回的类型包含无意义的泛型类型名称

诡异的文字类型--S为物语的关键

使用订阅时更新AG网格中的行

在保留类型的同时进行深层键名转换

不带其他属性的精确函数返回类型

类型';字符串|数字';不可分配给类型';未定义';.类型';字符串';不可分配给类型';未定义';

是否可以通过映射类型将函数参数约束为预定义类型?

界面中数组中的混合类型导致打字错误

对有效枚举值的常量字符串进行常规判断

TypeScrip-如何自动推断UNION变量的类型

如何在具有嵌套数组的接口中允许新属性

VUE 3类型';字符串';不可分配给类型';参考<;字符串&>

可以将JS文件放在tsconfig';s includes/files属性?或者,我如何让tsc判断TS项目中的JS文件?

const 使用条件类型时,通用类型参数不会推断为 const