TypeScript 类型断言错误:'此表达式不可调用类型'...' 没有调用签名' 是由缺少分号引起的

问题描述

这是我们原始代码的精简版:

  const start: number = 10
  const end: number = 20
  (someElement as HTMLInputElement).setSelectionRange(start,end)

然后在 20 下方有一条漂亮的红色小波浪线。指示此错误此表达式不可调用类型“Number”没有调用签名。我们找到了解决方案是添加一个分号:

  const start: number = 10
  const end: number = 20;
  (someElement as HTMLInputElement).setSelectionRange(start,end)

有谁知道为什么会这样编译?我假设正在编译成 javascript 的打字稿正在解释如下代码并尝试将 end 变量作为函数调用

  const start: number = 10
  const end: number = 20(someElement as HTMLInputElement).setSelectionRange(start,end)

解决方法

此行为并非特定于 TypeScript;您遇到的问题与使用纯 JavaScript 时遇到的问题相同。 TypeScript 编译器不会选择将正确的 TypeScript 编译成不正确的 JavaScript;相反,它尽职尽责地将奇怪的 TypeScript 转换为等效的奇怪的 JavaScript。

一般来说,如果行终止符之后的下一个标记可能在语法上有效,则 automatic semicolon insertion 不适用,唯一的例外是在特定位置中禁止使用行终止符 (有关这些地方的列表,请参阅上面的 MDN 链接)。 ( 之后的左括号 20 显然可以解释为函数调用的开始,这在语法上是有效的。并且因为在 20 之后没有禁止行终止符,所以没有插入分号。

在 TypeScript 中,您会收到一个编译器错误,警告您正在调用没有调用签名的 20。该错误是一件好事,因为它使您有机会在进入运行时之前通过插入自己的分号来修复代码。因为同样,如果您用纯 JavaScript 编写上述代码(例如,没有类型断言),JavaScript 运行时会以相同的方式解释代码,并且您会收到运行时错误而不是编译器警告:

// This is plain JS,not TS 
try {
  const someElement = document.getElementsByTagName("input").item(0);
  const start = 10
  const end = 20
  (someElement).setSelectionRange(start,end)
} catch (e) {
  console.log("OOPS I CAUGHT AN ERROR");
  console.log(e.message); // 20 is not a function
}

如果您运行该代码段(看不到 TypeScript 编译器),您会看到浏览器的 JavaScript 运行时发出 TypeError,表明 20 不是有效函数。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...