Ошибка утверждения типа TypeScript: «Это выражение не вызывается Тип» «не имеет сигнатуры вызовов» вызвана отсутствующей точкой с запятой

Это очень урезанная версия нашего исходного кода:

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

Затем была маленькая красная волнистая линия под 20. Указывая на эту ошибку: Это выражение не вызывается. Тип «Число» не имеет сигнатур вызовов. Мы разобрались, что решение - добавить точку с запятой:

  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)

person Ryan    schedule 06.01.2021    source источник


Ответы (1)


Это поведение не характерно для TypeScript; проблема, с которой вы столкнулись, такая же, как и с обычным JavaScript. Компилятор TypeScript не выбирает компиляцию правильного TypeScript в неправильный JavaScript; вместо этого он послушно трансформирует странный TypeScript в эквивалентный странный JavaScript.

Как правило, автоматическая вставка точки с запятой не работает. t применяется, если следующий токен после признака конца строки возможно синтаксически действителен, единственное исключение - это одно из конкретных мест, где запрещены обозначения конца строки (список этих мест см. по ссылке 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 не является допустимой функцией.

person jcalz    schedule 06.01.2021
comment
Хорошо сказано! Спасибо, jcalz. Просто из любопытства порекомендуете ли вы какие-либо альтернативные способы написания утверждений типа? - person Ryan; 06.01.2021
comment
Есть синтаксис угловых скобок, но это приведет к аналогичной проблеме, и синтаксис as в любом случае лучше (особенно для кода JSX / TSX). Моя настоящая рекомендация - просто использовать точки с запятой в конце операторов. Автоматическая вставка точки с запятой странно и усложняет понимание языка людьми. Думаю, в какой-то момент он всех укусит. - person jcalz; 06.01.2021